This might be a simple question:
Is there any difference between the two folowing:
def myfunc(a_list = [], **kwargs):
my_arg = kwargs.get('my_arg', None)
pass
and
def myfucn(a_list = [], my_arg = None):
pass
If not, which would be considered more pythonic?
Thanks,
-Matt
For a simple function, it's more Pythonic to explicitly define your arguments. Unless you have a legit requirement to accept any number of unknown or variable arguments, the **kwargs method is adding unnecessary complexity.
Bonus: Never initialize a list in the function definition! This can have unexpected results by causing it to persist because lists are mutable!
The first one can take virtually any keyword arguments provided (regardless of the fact that it only uses one of them), whereas the second can only take two. Neither is more Pythonic, you simply use the one appropriate for the task.
Also, the second is not "keyword arguments" but rather a "default value".
The second alternative allows my_arg to be passed as a positional rather than a keyword argument. I would consider it unpythonic to declare **kwargs when you don't actually use them for anything.
Related
In python, it is possible to define a function taking an arbitrary number of positional arguments like so:
def f(*args):
print(args)
f(1, 2, 3) # (1, 2, 3)
When called as f(a, b, c), all positional arguments are put together into a tuple.
This behavior is described in python 2 and 3 documentation, but I haven't found a PEP to it.
PEP 3132, introducing extended iterable unpacking (first, *middle, last = seqence) states under "Acceptance" that
Make the starred target a tuple instead of a list. This would be consistent with a function's *args, but make further processing of the result harder.
was discussed. If I write a wrapper, I may also want to further process arguments like so:
def force_type(position, type):
def wrapper(f):
def new(*args, **kwargs):
args = list(args) # Why?
args[position] = type(args[position])
return f(*args, **kwargs)
return new
return wrapper
#force_type(1, int)
def func(a, b, c):
assert isinstance(b, int)
This further processing is made harder by the fact args is a tuple. Were wrappers just not used at the early stages this was introduced? If so, why wasn't this changed in python3 with other compatibility breaking changes (PEP3132 favours ease of processing over consistency (which seems at least similar to compatibility in a compatibility- breaking change).
Why are a functions *args (still) a tuple even though a list allows easier further processing?
I don't know if this was the thinking behind it, but that ease of processing (even though instantiate a list with the tuple data is not that hard) would come at possible confusing behavior.
def fce1(*args):
fce2(args)
# some more code using args
def fce2(args):
args.insert(0, 'other_val')
fce1(1, 2, 3)
Could surprise people writing fce1 code not realizing that args they deal with later on are not what the function was called with.
I would also presume immutable types are easier to deal with internally and come with less overhead.
Why not? The thing about tuple is, that you can not change it after creation. This allows to increase speed of executing your script, and you do not really need a list for your function arguments, because you do not really need to modify the given arguments of a function.
Would you need append or remove methods for your arguments? At most cases it would be no. Do you want your program run faster. That would be yes. And that's the way the most people would prefer to have things. The *args thing returns tuple because of that, and if you really need a list, you can transform it with one line of code!
args = list(args)
So in general:
It speeds up your program execution. You do not it to change the arguments. It is not that hard to change it's type.
My best guess would be that if *args generates a list(mutable), it can lead to very surprising results for a multitude of situations. #Ondrej K. has given a great example. As an analogy, when having a list as a default argument, every function call might have different default arguments. This is the result of default arguments being evaluated only once, and this situation is not the most intuitive. Even the official python docs have a specific workaround for this exact situation.
Default parameter values are evaluated from left to right when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. This is generally not what was intended. A way around this is to use None as the default, and explicitly test for it in the body of the function, e.g.:
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
Source documentation
To summarize, I believe that *args is a tuple because having it as a list would cause all the problems associated with a mutable type (like slower speed) and the bigger issue would be that most do not expect function arguments to change.
Although I do agree that this implementation is very inconsistent with PEP-3132 and will cause confusion for most learners. I am very new to Python and it took me a while to understand what might be the reason for *args to be a tuple and not a list for the sake of consistency with PEP-3132's acceptance.
I have some code that looks like this:
from functools import lru_cache
#lru_cache()
def get_cheese(type):
print('{}? We\'re all out.'.format(type))
return None
get_cheese(type='cheddar')
get_cheese('cheddar')
print(get_cheese.cache_info())
cache_info() reports that there were two misses - yet I called the function with the same argument.
It actually took some doing, but I figured out that it's because in one instance I was using the keyword arg, and the other I was using a positional argument.
But why?
The wrapper created by functools.lru_cache makes no attempt to inspect or copy the signature of the wrapped function. The Python version is defined as
def wrapper(*args, **kwargs):
...
key = make_key(args, kwds, typed)
...
and as you can see, it builds the key used in the cache based on args and kwargs, without knowing whether any positional or keyword arguments are equivalent. The C version similarly builds the key without caring about the original signature.
As for why it's designed that way? I'm not aware of the original rationale. It could have been deliberate, either for simplicity of implementation or to avoid the overhead of matching keyword arguments to positionals, or it could have been an oversight. If you think changing it would be worthwhile, you could bring it up on the issue tracker.
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.
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.
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.
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).
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.
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)
While I'm going through Python code and seeing functions called, I notice things like
functionCall(argument='something')
or
someclass.functionCall(argument='something')
I've played around with it and noticed you have to name that variable with the same name as the one in the scope of the function or class function itself. Is that just a convention (for useful naming) or is there more to it that I'm missing?
Those are just standard keyword arguments.
They are mainly useful when calling functions that usually assume default values, but the user is interested in passing a custom value without affecting the other defaults.
For example:
def foo(a='a', b='b', c='c'):
print a + b + c
Then:
>>> foo()
'abc'
>>> foo(c='x') # don't know or care about a and b's value
'abx'
This is called a keyword argument. Keyword arguments have a couple distinct advantages:
They can be specified in any order by the caller.
They have default values, which means the caller doesn't have to provide a value for each argument if the defaults are sensible.
They can make code more readable. For example, foo(width=100, height=200) is easier to understand than foo(100, 200). It is also easier to use, because you don't have to remember whether the function takes width,height or height,width.
It is good to have named arguments as arguments can be specified in any order by using named arguments.
Even required arguments (like object, which has no default value) can be named, and named arguments can appear in any order.
Also see This
Python's argument passing mechanisms are extremely flexible.
cons: too many arguments to a function. Solutions: split into multiple functions, pass some args together in a dictionary or object.
cons: bad variable names. Solution: give variables more descriptive names.
Or remember the correct order .. :)
class xyz:
def __init__ (self, a='1', b='2'):
print a,b
xyz(b=3,a=4)
xyz(a=5,b=6)
>>4 3
>>5 6
these are keyword parameters. They enable you to pass parameters in any order (useful for skipping optional parameters)
Please note though, calling functions that way comes with a little bit of overhead:
def test(a,b,c):
return a+b+c
def t1():
return test(1,2,3)
def t2():
return test(a=1, b=2, c=3)
timeit(t1)
0.23918700218200684
timeit(t2)
0.2716050148010254
I'm going through python and I was wondering what are the advantages of using the *args as a parameter over just passing a list as a parameter, besides aesthetics?
Generally it's used to either pass a list of arguments to a function that would normally take a fixed number of arguments, or in function definitions to allow a variable number of arguments to be passed in the style of normal arguments. For instance, the print() function uses varargs so that you can do things like print(a,b,c).
One example from a recent SO question: you can use it to pass a list of range() result lists to itertools.product() without having to know the length of the list-of-lists.
Sure, you could write every library function to look like this:
def libfunc1(arglist):
arg1 = arglist[1]
arg2 = arglist[2]
...
...but that defeats the point of having named positional argument variables, it's basically exactly what *args does for you, and it results in redundant braces/parens, since you'd have to call a function like this:
libfunc1([arg1val,arg2val,...])
...which looks very similar to...
libfunc1(arg1val,arg2val,...)
...except with unnecessary characters, as opposed to using *args.
That is for flexibility.
It allows you to pass on the arguments, without knowing how much you need. A typical example:
def f(some, args, here): # <- this function might accept a varying nb of args
...
def run_f(args, *f_args):
do_something(args)
# run f with whatever arguments were given:
f(*f_args)
Make sure to check out the ** keyword version.