diff --git a/README.md b/README.md index 79eb8c6..f9b5684 100755 --- a/README.md +++ b/README.md @@ -83,6 +83,8 @@ So, here ya go... - [💡 Explanation:](#-explanation-16) - [Needle in a Haystack](#needle-in-a-haystack) - [💡 Explanation:](#-explanation-17) + - [Let's see if you can guess this?](#lets-see-if-you-can-guess-this) + - [💡 Explanation:](#-explanation-18) - [Minor Ones](#minor-ones) - [TODO: Hell of an example!](#todo-hell-of-an-example) - [Contributing](#contributing) @@ -1396,6 +1398,62 @@ tuple() --- +### Let's see if you can guess this? + +Originally, suggested by @PiaFraus in [this](https://github.com/satwikkansal/wtfPython/issues/9) issue. + +```py +a, b = a[b] = {}, 5 +``` + +**Output:** +```py +>>> a +{5: ({...}, 5)} +``` + +#### 💡 Explanation: + +* According to [Python language reference](https://docs.python.org/2/reference/simple_stmts.html#assignment-statements), assignment statements have the form + ``` + (target_list "=")+ (expression_list | yield_expression) + ``` + and + > An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right. + +* The `+` in `(target_list "=")+` means there can be **one or more** target lists. In this case, target lists are `a, b` and `a[b]` (note the expression list is exactly one, which in our case is `{}, 5`). + +* After the expression list is evaluated, it's value is unpacked to the target lists from **left to right**. So, in our case, first the `{}, 5` tuple is unpacked to `a, b` and we now have `a = {}` and `b = 5`. + +* `a` is now assigned to `{}` which is a mutable object. + +* The second target list is `a[b]` (you may expect this to throw an error because both `a` and `b` have not been defined in the statements before. But remember, we just assigned `a` to `{}` and `b` to `5`). + +* Now, we are setting the key `5` in the dictionary to the tuple `({}, 5)` creating a circular reference (the `{...}` in the output refers to the same object that `a` is already referencing). Another simpler example of circular reference could be + ```py + >>> some_list = some_list[0] = [0] + >>> some_list + [[...]] + >>> some_list[0] + [[...]] + >>> some_list is some_list[0] + [[...]] + ``` + Similar is the case in our example (`a[b][0]` is the same object as `a`) + +* So to sum it up, you can break the example down to + ```py + a, b = {}, 5 + a[b] = a, b + ``` + And the circular reference can be justified by the fact that `a[b][0]` is the same object as `a` + ```py + >>> a[b][0] is a + True + ``` + +--- + ### Minor Ones * `join()` is a string operation instead of list operation. (sort of counter-intuitive at first usage)