Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where does python argument unpacking fall into the order of operations?

Tags:

python

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?

like image 770
Ben J Avatar asked Oct 22 '13 18:10

Ben J


People also ask

What is argument unpacking 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, * .

What is the unpacking operator in Python?

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.

What is the significance of unpacking the element in tuple through asterisk (*)?

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.


2 Answers

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.

like image 64
abarnert Avatar answered Oct 13 '22 00:10

abarnert


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.

like image 20
poke Avatar answered Oct 12 '22 23:10

poke