Python optional parameters
optional-arguments, python
Solution
You need to understand how default values work in order to use them effectively.
Functions are objects. As such, they have attributes. So, if I create this function:
>>> def f(x, y=[]):
y.append(x)
return y
I've created an object. Here are its attributes:
>>> dir(f)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',
'__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__',
'__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals',
'func_name']
One of them is `func_defaults`. That sounds promising, what's in there?
>>> f.func_defaults
([],)
That's a tuple that contains the function's default values. If a default value is an object, the tuple contains an instance of that object.
This leads to some fairly counterintuitive behavior if you're thinking that `f` adds an item to a list, returning a list containing only that item if no list is provided:
>>> f(1)
[1]
>>> f(2)
[1, 2]
But if you know that the default value is an object instance that's stored in one of the function's attributes, it's much less counterintuitive:
>>> x = f(3)
>>> y = f(4)
>>> x == y
True
>>> x
[1, 2, 3, 4]
>>> x.append(5)
>>> f(6)
[1, 2, 3, 4, 5, 6]
Knowing this, it's clear that if you want a default value of a function's parameter to be a new list (or any new object), you can't simply stash an instance of the object in `func_defaults`. You have to create a new one every time the function is called:
>>>def g(x, y=None):
if y==None:
y = []
y.append(x)
return y
Problem
Guys, I just started python recently and get confused with the optional parameters, say I have the program like this: ``` class B: pass class A: def __init__(self, builds = B()): self.builds = builds ``` If I create A twice ``` b = A() c = A() ``` and print their builds ``` print b.builds print c.builds ``` I found they are using the exactly same object, ``` <__main__.B instance at 0x68ee0> <__main__.B instance at 0x68ee0> ``` But it is not what I want, since if `b` changed some internal state of builds, the one in `c` object will also be changed. Is it possible to recreate this optional parameters each time by using this optional parameters syntax?