In this project, the file RPS.py shows an example function . The example function is defined with two arguments.
def player(prev_play, opponent_history = ):
Could anyone help me to understand why the function variable “opponent_history” managed to continue tracking the history when it has been called with in the for loop? I would expecting it to be an empty list every time when the function is called. But it almost acted as a global variable which continue append between each for loop!
Thank you alkapwn3d . I was thinking the same way as well. However this is not the case!
As you can see the screenshot, this is the 4th call within the for loop, the prev_play just capture the last result, not the history.
So, this is a bit counter-intuitive at first, and it took me some reading to figure out what is going on.
In Python, functions are first class objects. What this means is that a function can hold data, just like any other object. The default parameter is a piece of data held by its function, and this data is mutable in certain cases.
Here is a smaller example you can play around with:
Thank you JeremyLT! Really appreciate the example. Do you know why the following example, the s variable doesn’t behave the same way as the default list parameter?
def foo(x, history=[]):
history.append(x)
print(history)
foo("a")
foo("b")
history
In [27]: foo("c")
['a', 'b', 'c']
In [28]: foo
Out[28]: <function __main__.foo(x, history=['a', 'b', 'c'])>
In [29]: def bar(x, s=""):
...: s +=x
...: print(s)
...:
In [30]: bar("a")
a
In [31]: bar("sdfs")
sdfs
In [32]: bar
Out[32]: <function __main__.bar(x, s='')>
Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.
After reading your answer again, it financially make sense now. The list argument is mutable and it evaluated when the function was defined. This is why it didn’t work with the bar func when the argument is string. Thank you!