21

I have started to learn python, and I would like to ask you about something which I considered a little magic in this language.

I would like to note that before learning python I worked with PHP and there I haven't noticed that.

What's going on - I have noticed that some call constructors or methods in Python are in this form.

object.call(variable1 = value1, variable2 = value2)

For example, in FLask:

app.run(debug=True, threaded=True)

Is any reason for this convention? Or is there some semantical reason outgoing from the language fundamentals? I haven't seen something like that in PHP as often as in Python and because I'm really surprised. I'm really curious if there is some magic or it's only convention to read code easier.

Petr Jirásek
  • 453
  • 1
  • 5
  • 17
  • 3
    http://docs.python.org/2/tutorial/controlflow.html#keyword-arguments explains it all fairly well. – Robᵩ Aug 12 '13 at 19:46
  • I had the exact opposite experience a few years ago, coming to PHP from Python and being confused when `f($a=true)` was accepted, but didn't do what I thought it did. – Ben Aug 12 '13 at 22:02

5 Answers5

29

These are called keyword arguments, and they're usually used to make the call more readable.

They can also be used to pass the arguments in a different order from the declared parameters, or to skip over some default parameters but pass arguments to others, or because the function requires keyword arguments… but readability is the core reason for their existence.

Consider this:

app.run(True, False)

Do you have any idea what those two arguments mean? Even if you can guess that the only two reasonable arguments are threading and debugging flags, how can you guess which one comes first? The only way you can do it is to figure out what type app is, and check the app.run method's docstring or definition.

But here:

app.run(debug=True, threaded=False)

It's obvious what it means.


It's worth reading the FAQ What is the difference between arguments and parameters?, and the other tutorial sections near the one linked above. Then you can read the reference on Function definitions for full details on parameters and Calls for full details on arguments, and finally the inspect module documentation on kinds of parameters.

This blog post attempts to summarize everything in those references so you don't have to read your way through the whole mess. The examples at the end should also serve to show why mixing up arguments and parameters in general, keyword arguments and default parameters, argument unpacking and variable parameters, etc. will lead you astray.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • It's worth pointing out that a function can accept keyword arguments that aren't explicitly defined via the `**kwargs` argument. – chepner Aug 12 '13 at 19:50
  • 1
    @chepner: Well, maybe, but only if you also explain about keyword parameters, and about the *args parameter, and about passing variable arguments and keyword dicts, which makes things a lot more complicated. It's worth understanding the basics first, and then reading the rest of the tutorial… – abarnert Aug 12 '13 at 19:52
  • @chepner: I've tried to add sufficient links that someone can actually find the information they need to get to the point where `**kwargs` makes sense, and then learn exactly how it works. But probably there's a better way to include that information. Any suggestions? – abarnert Aug 12 '13 at 21:00
5

Specifying arguments by keyword often creates less risk of error than specifying arguments solely by position. Consider this function to compute loan payments:

def pmt(principal, interest, term):
    return **something**;

When one tries to compute the amortization of their house purchase, it might be invoked thus:

payment = pmt(100000, 4.2, 360)

But it is difficult to see which of those values should be associated with which parameter. Without checking the documentation, we might think it should have been:

payment = pmt(360, 4.2, 100000)

Using keyword parameters, the call becomes self-documenting:

payment = pmt(principal=100000, interest=4.2, term=360)

Additionally, keyword parameters allow you to change the order of the parameters at the call site, and everything still works correctly:

# Equivalent to previous example
payment = pmt(term=360, interest=4.2, principal=100000)

See http://docs.python.org/2/tutorial/controlflow.html#keyword-arguments for more information.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
0

They are arguments passed by keywords. There is no semantical difference between keyword arguments and positional arguments.

They are often used like "options", and provide a much more readable syntax for this circumstance. Think of this:

>>> sorted([2,-1,3], key=lambda x: x**2, reverse=True)
[3, 2, -1]

Versus(python2):

>>> sorted([2,-1,3], None, lambda x: x**2, True)
[3, 2, -1]

In this second example can you tell what's the meaning of None or True?

Note that in keyword only arguments, i.e. arguments that you can only specify using this syntax, were introduced in python3. In python2 any argument can be specified by position(except when using **kwargs but that's another issue).

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
  • The last part of this is misleading. Keyword-only _parameters_ were introduced in Python 3; there's no such thing as keyword-only arguments. But everything other than the final note is correct, and nicely explained. – abarnert Aug 12 '13 at 21:02
  • @abarnert I use the words *argument* and *parameter* as synonyms. I don't see why they should be distinguished. I have always lived with this ambiguity and it doesn't give any particular problem. In fact, the last paragraph **clearly** refers to what you call *parameters* since otherwise the sentence *"arguments that you can only specify using this syntax,"* does't have any meaning, hence there is no ambiguity. – Bakuriu Aug 12 '13 at 21:13
  • Python explicitly distinguishes the two terms. The Python FAQ has [an entry](http://docs.python.org/3/faq/programming.html#faq-argument-vs-parameter) that explains why. More generally, every language has such a distinction… but some of them use different terminology (like "actual parameter" vs. "formal parameter"). The fact that you can sometimes get away with mixing them up doesn't mean you should; it means you should be extra careful not to, because that will lead you astray when you deal with cases where you can't get away with it—and will often lead your readers astray even when you can. – abarnert Aug 12 '13 at 21:48
-1

There is no "magic".

A function can take:

  • Positional arguments (args)
  • Keyworded arguments (kwargs)

Always is this order.

Try this:

def foo(*args, **kwargs):
    print args
    print kwargs

foo(1,2,3,4,a=8,b=12)

Output:

(1, 2, 3, 4)
{'a': 8, 'b': 12}

Python stores the positional arguments in a tuple, which has to be immutable, and the keyworded ones in a dictionary.

DevLounge
  • 8,313
  • 3
  • 31
  • 44
  • 1
    Python only stores positional arguments whose index doesn't match a keyword-or-positional parameter (or a positional-only parameter, but you don't have those in functions defined in Python) in the var-positional sequence, and it only stores keyword arguments whose name doesn't match a keyword-or-positional or keyword-only parameter in the var-keyword mapping. Since the OP is asking about a function that has two keyword-or-positional parameters, this isn't relevant here. No such dict is constructed or passed anywhere. – abarnert Aug 12 '13 at 21:01
  • I agree, but can't an answer try to show some additional things not already explained by other answers? – DevLounge Aug 12 '13 at 21:07
  • Sure, an answer can be useful even though it's a digression… but a misleading answer doesn't become useful just because it's a digression. – abarnert Aug 12 '13 at 21:50
-2

The main utility of the convention is that it allows for setting certain inputs when there may be some defaults in between. It's particularly useful when a function has many parameters, most of which work fine with their defaults, but a few need to be set to other values for the function to work as desired.

example:

def foo(i1, i2=1, i3=3, i4=5):
   # does something


foo(1,2,3,4)

foo(1,2,i4=3)

foo(1,i2=3)

foo(0,i3=1,i2=3,i4=5)
Jiminion
  • 5,080
  • 1
  • 31
  • 54
  • 1
    Setting default values when *defining* the function is a somewhat separate issue from using keyword arguments when *calling* the function. – chepner Aug 12 '13 at 19:49
  • I don't think so. If you are bypassing an input via keywords, then the bypassed inputs need/should have default values, no? – Jiminion Aug 12 '13 at 19:50
  • 1
    @Jim: No. Read the FAQ [What is the difference between arguments and parameters](http://docs.python.org/3/faq/programming.html#what-is-the-difference-between-arguments-and-parameters), and then look at how they're defined. You can pass keyword arguments for parameters that have no defaults. For example, `def f(a, b): pass`, then `f(b=1, a=2)` works just fine. – abarnert Aug 12 '13 at 19:53
  • @Jim Defaults have *nothing* to do with being keyword arguments. For example `def f(*, a): print(a)` is a function with a keyword argument without a default value(python3). You can also see a side effect of this when you use unpacking of positional arguments mixed with keyword arguments in python2. – Bakuriu Aug 12 '13 at 19:53
  • 1
    My point was that you can make use of default values without calling the function using keyword arguments, and you can use keyword arguments with a function that does not specify default parameter values. – chepner Aug 12 '13 at 19:53
  • @Bakuriu: No, it's a function with a keyword-only parameter. That's not the same thing as a keyword argument. – abarnert Aug 12 '13 at 19:54
  • @chepner: Exactly. Keyword arguments, keyword-only parameters, and default parameter values are not entirely unrelated, but they're by no means all the same thing, and a lot of people confuse themselves by mixing them up. Good explanation without resorting to jargon like I did. – abarnert Aug 12 '13 at 19:54
  • @abarnert, yes, you can, but practically, they are limited. You couldn't say (in your example) f(b=1). – Jiminion Aug 12 '13 at 19:55
  • @abarnert, I didn't mean to imply they were the same thing. But they often go hand in hand. – Jiminion Aug 12 '13 at 19:57
  • @Jim: Sure, you obviously can't call a function without passing arguments for all non-defaulted parameters. That has nothing to do with keywords. I don't know how to explain it any clearer than chepner; if you don't get why your answer is wrong, you need to read the tutorial and FAQ sections. – abarnert Aug 12 '13 at 19:58
  • @abarnert, I understand you. We just disagree if they are practically (if not technically) related. Made an effort to clarify. – Jiminion Aug 12 '13 at 20:02
  • @Jim: Nobody's saying they're not related. In fact, I explicitly said they _are_ related. But that doesn't mean you can use them interchangeably. It's like saying that function definitions and function calls are related, and therefore you can call a function with the `def` keyword. – abarnert Aug 12 '13 at 21:03