Python Function: Optional Argument Evaluated Once?
Solution 1:
In Python, functions are objects too, and the defaults are stored with the function object. Defaults are not locals; it is just that when the function is called, the arguments are bound to a default when not given an explicit value.
When Python encounters a def <functionname>(<arguments>):
statement, it creates a function object for you there and then; this is 'definition time'; the function is not called but merely created. It is then that defaults are evaluated and stored, in an attribute on the function object.
Then when you call the function, the defaults have already been created and are used when you didn't provide a more concrete value for the argument. Because the defaults are stored with the function object, you get to see changes to mutable objects between function calls.
The locals are still cleared up of course, but as they are references (all identifiers in Python are), the objects they were bound to are only cleared up if nothing else is referencing them anymore either.
You can take a look a the defaults of any function object:
>>>deffoo(bar='spam', eggs=[]):... eggs.append(bar)...return eggs...>>>foo.__defaults__
('spam', [])
>>>foo()
['spam']
>>>foo.__defaults__
('spam', ['spam'])
>>>foo() is foo.__defaults__[1]
True
The foo()
function has a __defaults__
attribute, a tuple of default values to use when no values for the arguments have been passed in. You can see the mutable list change as the function is called, and because the function returns the eggs
list, you can also see that it is the exact same object as the second value in that tuple.
If you don't want your defaults to be shared and instead need a new value for a parameter every time the function is called, but the parameter is not given, you need to set the default value to a sentinel object. If your parameter is still set to that sentinel in the function body, you can execute code to set a fresh default value. None
is usually the best choice:
deffoo(bar='spam', eggs=None):
if eggs isNone:
eggs = []
If it should be possible to use None
as a non-default value, use a singleton sentinel created beforehand:
_sentinel = object()
deffoo(bar='spam', eggs=_sentinel):
if eggs is _sentinel:
eggs = []
Solution 2:
A function is just an object in python, that is created using the def
syntax. Default values are stored within the function object when the function is defined, and they are not re-evaluated later.
This is sometimes used to create function variables that persist to subsequent invocations. You can use the __defaults__
methods to check what the default values are for your function.
A common way to initialize new objects instead of reusing the same is:
deff(a, L=None):
if L isNone:
L = []
L.append(a)
return L
You can check this page for more details.
Solution 3:
Sorry this answer was meant for a different question, but I'll leave it here as a reference if anyone who wants to look at it. Define once means that at the first point when the code is executed, the default variable gets assigned to an object which is retained within the function object itself.
Notice only 1 object address gets printed, the default list object is used.
deff(a, L=[]):
print("id default: ", id(L))
L.append(a)
print("id used: ", id(L)
return L
Notice 2 different object addresses are printed, when you perform L=[] within the function, you are binding L to a different list object, therefore the default list object does not get change.
deff(a, L=[]):
print("id default: ", id(L))
if L == []:
L = []
L.append(a)
print("id used: ", id(L))
return L
The function above is basically the same as the one below except it uses the None object instead of a empty list object.
deff(a, L=None):
print("id default", id(L))
if L isNone:
L = []
L.append(a)
print("id used: ", id(L))
return L
Post a Comment for "Python Function: Optional Argument Evaluated Once?"