Hello
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!
def player(prev_play, opponent_history=[]):
    opponent_history.append(prev_play)
    guess = "R"
    if len(opponent_history) > 2:
        guess = opponent_history[-2]
    return guess
https://repl.it/@freeCodeCamp/fcc-rock-paper-scissors#README.md
By adding  print('opponent_history:', opponent_history) to the function we can see the list continue to expand between each call.
             
            
              
              
              
            
            
           
          
            
            
              the first time player(prev_play) is called it uses p?_prev_play as the argument
at the end of every loop in play() in RPS_game, the new result of the last player() call is stored by rewriting p?_prev_play…
so the next time player() is called, it takes the previously stored p?_prev_play and appends it to opponent_history in the newly called function
…um, i think that makes sense. let me know if it doesnt
             
            
              
              
              
            
            
           
          
            
            
              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.
             
            
              
              
              
            
            
           
          
            
            
              ugh…youre right. that makes no sense
             
            
              
              
              
            
            
           
          
            
            
              From this screenshot you can clear see, the  variable has never been destroyed  within the for loop!
             
            
              
              
              
            
            
           
          
            
            
              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:
             
            
              
              
              2 Likes
            
            
           
          
            
            
              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='')>
             
            
              
              
              
            
            
           
          
            
            
              I think here is the answer!  https://docs.python-guide.org/writing/gotchas/
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.
             
            
              
              
              2 Likes
            
            
           
          
            
            
              
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!
             
            
              
              
              2 Likes
            
            
           
          
            
            
              I learned a lot from your question and your experience working through the problem. IT was a great read.
Thanks for sharing
             
            
              
              
              2 Likes