What is the default scope of a parameter in Python?

When you define a function in Python with an array parameter, what is the scope of this parameter?

This example is taken from a Python tutorial:

def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3) 

Print

 [1] [1, 2] [1, 2, 3] 

I'm not quite sure if I understand what is happening here. Does this mean that the scale of the array is outside the function? Why does the array remember its values ​​from the call to call? Coming from other languages, I would expect this behavior only if the variable was static. Otherwise, it seems like it should be reset every time. And actually, when I tried the following:

 def f(a): L = [] L.append(a) return L 

I got the expected behavior (the array was reset for each call).

So, it seems to me that I just need the string def f(a, L=[]): - what is the scope of the variable L ?

+17
scope python parameters default-value function-calls
Feb 25 2018-10-25T00
source share
7 answers

Scope, as you would expect.

It may be surprising that the default value is calculated only once and reused, so each time you call the function, you get the same list, not a new list initialized [].

The list is saved in f.func_defaults .

 def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3) print f.func_defaults f.func_defaults = (['foo'],) # Don't do this! print f(4) 

Result:

 [1] [1, 2] [1, 2, 3] ([1, 2, 3],) ['foo', 4] 
+16
Feb 25 2018-10-25T00
source share

The volume of the variable L behaves as you expect.

The “problem” is with the list that you create with [] . Each time you call this function, Python does not create a new list. L gets the assigned same list every time it is called, so the function “remembers” previous calls.

So this is what you have:

 mylist = [] def f(a, L=mylist): L.append(a) return L 

The Python tutorial puts it this way :

The default value is evaluated only once. This matters when by default it is a mutable object, such as a list, dictionary, or instances of most classes.

and offers the following way of encoding expected behavior:

 def f(a, L=None): if L is None: L = [] L.append(a) return L 
+4
Feb 25 2018-10-25T00
source share

There's even less “magic” than you might suspect. It is equivalent

 m = [] def f(a, L=m): L.append(a) return L print f(1) print f(2) print f(3) 

m is created only once.

+3
Feb 25 '10 at 15:30
source share

Say you have the following code:

 def func(a=[]): a.append(1) print("A:", a) func() func() func() 

You can use python indentation to help you understand what is going on. Everything that is on the edge of the left margin is executed when the file is executed. Everything indented is compiled into a code object that runs when func() called. Thus, the function is defined and its arguments are set by default once when the program starts (because the def statement is hidden to the left).

What it does with the default arguments is an interesting problem. In python 3, it provides most of the function information in two places: func.__code__ and func.__defaults__ . In python 2, func.__code__ was func.func_code func.__defaults__ was func.func_defaults . Later versions of python 2, including 2.6, have both sets of names to help move from python 2 to python 3. I will use the more modern __code__ and __defaults__ . If you are stuck on an older python, the concepts are the same; just the names are different.

The default values ​​are stored in func.__defaults__ and retrieved each time the function is called.

Thus, when you define the function above, the body of the function is compiled and stored in variables under __code__ , which must be executed later, and the default arguments are stored in __defaults__ . When you call a function, it uses the values ​​in __defaults__ . If these values ​​can be changed for any reason, only a modified version is available for this.

Play around defining various functions in an interactive interpreter and see what you can understand about how python creates and uses functions.

+1
Feb 25 2018-10-25T00
source share

The “problem” is that L=[] is evaluated only once, that is, when the file is compiled. Python goes through each line of the file and compiles it. By the time def reached with the default parameter, it instantiates the list once.

If you put L = [] inside the function code, the instance will not be created at compile time (in fact, compilation time can also be called part of the run time), because Python compiles the function code, but does not call it. This way you get a new instance of the list, because the creation is done every time you call the function (and not once at compile time).

The solution to this problem is to not use mutable objects as default parameters or only fixed instances of type None :

 def f(a, L = None): if l == None: l = [] L.append(a) return L 

Note that in both of the cases that you described, the region L is the region of functions.

0
Feb 25 '10 at 15:39
source share

An explanation is given in the answers to this question . To summarize this:

Functions in Python are a kind of object. Because they are a kind of object, they act like objects when instantiated. A function, if defined with a mutable attribute as the default argument, is exactly the same as a class with a static attribute, which is a mutable list.

Lennart Regebro has a good explanation and the answer to Roberto Liffredo's question is excellent.

To adapt Lennart's answer ... if I have a BananaBunch class:

 class BananaBunch: bananas = [] def addBanana(self, banana): self.bananas.append(banana) bunch = BananaBunch() >>> bunch <__main__.BananaBunch instance at 0x011A7FA8> >>> bunch.addBanana(1) >>> bunch.bananas [1] >>> for i in range(6): bunch.addBanana("Banana #" + i) >>> for i in range(6): bunch.addBanana("Banana #" + str(i)) >>> bunch.bananas [1, 'Banana #0', 'Banana #1', 'Banana #2', 'Banana #3', 'Banana #4', 'Banana #5'] // And for review ... //If I then add something to the BananaBunch class ... >>> BananaBunch.bananas.append("A mutated banana") //My own bunch is suddenly corrupted. :-) >>> bunch.bananas [1, 'Banana #0', 'Banana #1', 'Banana #2', 'Banana #3', 'Banana #4', 'Banana #5', 'A mutated banana'] 

How does this relate to features? Functions in Python are objects . This is repeated. Functions in Python are objects .

Therefore, when you create a function, you create an object. When you give a function a mutable default value, you populate this attribute of the object with a mutable value, and each time you call this function, you are working with the same attribute. Therefore, if you use a mutable call (e.g. append), you are modifying the same object as if you were adding bananas to the bunch object.

0
Feb 25 '10 at 15:40
source share

You should keep in mind that python is an interpreted language. What happens here when the f function is defined, it creates a list and assigns the default parameter L to the f function. Later, when you call this function, the same list is used as the default parameter. In short, the code in the line "def" is executed only once when the function is defined. This is an ordinary python python, from which I fell myself.

 def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3) 

Other answers here included idiom suggestions to fix this problem. I would suggest the following:

 def f(a, L=None): L = L or [] L.append(a) return L 

It uses either a short circuit to either accept the passed "L" or create a new list.

The answer to your question about scope is that "L" has scope within the function "f", but since the default parameters are assigned only once to one list, and not every time you call a function that behaves like this as if the default parameter "L" has a global scope.

-one
Feb 25 '10 at 15:52
source share



All Articles