http://docs.python.org/2/reference/expressions.html#operator-precedence
My guess is that it falls into one of the buckets above dict lookups since
func(*mydict[mykey])
does the dictionary lookup first. Is there a better chart than my initial link that goes into more detail regarding order of operations in python?
Unpacking in Python refers to an operation that consists of assigning an iterable of values to a tuple (or list ) of variables in a single assignment statement. As a complement, the term packing can be used when we collect several values in a single variable using the iterable unpacking operator, * .
Both * and ** are the operators that perform packing and unpacking in Python. The * operator (quite often associated with args) can be used with any iterable (such as a tuple, list and strings), whereas the ** operator, (quite often associated with kwargs) can only be used on dictionaries.
The * operator is an unpacking operator that will unpack the values from any iterable object, such as lists, tuples, strings, etc… And that's it! The asterisk, *, or unpacking operator, unpacks num_list, and passes the values, or elements, of num_list as separate arguments to the num_sum function.
The unpacking *
is not an operator; it's part of the call syntax. It's defined under Calls, where you can see that:
["," "*" expression]
… can be part of an argument_list
in two different places. (The semantics are described in the paragraphs starting "If there are more positional…" and "If the syntax…".)
So it takes any expression
. You can see that no operator takes a full expression
as its direct argument. So, if you want to loosely consider *
an operator, it binds more loosely than any operator. But just remember that it isn't actually an operator.
Also keep in mind that this was all changed in Python 3.x. But the basic idea is the same—both argument unpacking and assignment unpacking take an expression
, not just a primary
, and therefore loosely-speaking bind more loosely than any operator, which all take a primary
or something more specific.
Meanwhile, you might want to try running the parser on your code to see what it does:
>>> import ast
>>> tree = ast.parse('func(*mydict[mykey])')
>>> ast.dump(tree)
"Module(body=[Expr(value=Call(func=Name(id='func', ctx=Load()), args=[], keywords=[],
starargs=Subscript(value=Name(id='mydict', ctx=Load()),
slice=Index(value=Name(id='mykey', ctx=Load())), ctx=Load()), kwargs=None))])"
You can see that the entire Subscript
expression ends up as the starargs
to the Call
.
The ast
module uses the Abstract Grammar rather than the one described in the reference manual. It has different names for things, and doesn't handle some things that are considered part of the grammar but actually done at a higher level than the parser, and so on—but, on the other hand, it's a lot easier to take in all at once. You can see that an expr
used for starargs
can be a Subscript
.
As BrenBarn mentioned in the comments, the unpacking is defined as part of function calls (Python 2 and 3) and assignment statements (Python 3).
So no, it will never take part of the operator precedence because it isn’t an operator.
How do I know that this won't try to unpack "mydict" in this example? Or is this something that the language parser handles.
In your example, func(*mydict[mykey])
, the specification for the function call applies. So let’s try to parse that manually.
The base part is matched by the definition of call
, so *mydict[mykey]
is the argument_list
. And in the argument list, it will be parsed as "*" expression
, with mydict[mykey]
being the expression. As such, the parser will never apply the unpacking first, because the grammar simply doesn’t specify a case where after "*" expression
another part in brackets follows.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With