Learning Python - Mark Lutz [249]
The actual matching algorithm Python uses is a bit more complex (it must also account for keyword-only arguments in 3.0, for instance), so we’ll defer to Python’s standard language manual for a more exact description. It’s not required reading, but tracing Python’s matching algorithm may help you to understand some convoluted cases, especially when modes are mixed.
* * *
Note
In Python 3.0, argument names in a function header can also have annotation values, specified as name:value (or name:value=default when defaults are present). This is simply additional syntax for arguments and does not augment or change the argument-ordering rules described here. The function itself can also have an annotation value, given as def f()->value. See the discussion of function annotation in Chapter 19 for more details.
* * *
Keyword and Default Examples
This is all simpler in code than the preceding descriptions may imply. If you don’t use any special matching syntax, Python matches names by position from left to right, like most other languages. For instance, if you define a function that requires three arguments, you must call it with three arguments:
>>> def f(a, b, c): print(a, b, c)
...
Here, we pass them by position—a is matched to 1, b is matched to 2, and so on (this works the same in Python 3.0 and 2.6, but extra tuple parentheses are displayed in 2.6 because we’re using 3.0 print calls):
>>> f(1, 2, 3)
1 2 3
Keywords
In Python, though, you can be more specific about what goes where when you call a function. Keyword arguments allow us to match by name, instead of by position:
>>> f(c=3, b=2, a=1)
1 2 3
The c=3 in this call, for example, means send 3 to the argument named c. More formally, Python matches the name c in the call to the argument named c in the function definition’s header, and then passes the value 3 to that argument. The net effect of this call is the same as that of the prior call, but notice that the left-to-right order of the arguments no longer matters when keywords are used because arguments are matched by name, not by position. It’s even possible to combine positional and keyword arguments in a single call. In this case, all positionals are matched first from left to right in the header, before keywords are matched by name:
>>> f(1, c=3, b=2)
1 2 3
When most people see this the first time, they wonder why one would use such a tool. Keywords typically have two roles in Python. First, they make your calls a bit more self-documenting (assuming that you use better argument names than a, b, and c). For example, a call of this form:
func(name='Bob', age=40, job='dev')
is much more meaningful than a call with three naked values separated by commas—the keywords serve as labels for the data in the call. The second major use of keywords occurs in conjunction with defaults, which we turn to next.
Defaults
We talked about defaults in brief earlier, when discussing nested function scopes. In short, defaults allow us to make selected function arguments optional; if not passed a value, the argument is assigned its default before the function runs. For example, here is a function that requires one argument and defaults two:
>>> def f(a, b=2, c=3): print(a, b, c)
...
When we call this function, we must provide a value for a, either by position or by keyword; however, providing values for b and c is optional. If we don’t pass values to b and c, they default to 2 and 3, respectively:
>>> f(1)
1 2 3
>>> f(a=1)
1 2 3
If we pass two values, only c gets its default, and with three values, no defaults are used:
>>> f(1, 4)
1 4 3
>>> f(1, 4, 5)
1 4 5
Finally, here is how the keyword and default features interact. Because they subvert the normal left-to-right positional mapping, keywords allow us to essentially skip over arguments with defaults:
>>> f(1, c=6)
1 2 6
Here, a gets 1 by position, c gets 6 by keyword, and b, in between, defaults