The default design parameters Python function [original]

 

In Python tutorial for default parameters to a "important warning" example:

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

print(f(1))
print(f(2))
print(f(3))

The default value only once, did not say why. It will print out the results:

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

Because the school's first language is Ruby, so it feels a little strange. But certainly some method to store variable L. f

 

Ready knowledge: Pointer

p points to immutable objects, such as numbers. P is equivalent to a pointer to a different memory address.

p points to mutable objects, such as list. list itself changed and will not change the memory address list object itself is located. So p at the memory address remain unchanged.

>>> p = 1
>>> id(p)
4523801232
>>> p = p + 1
>>> id(p)
4523801264
>>> p = 11
>>> id(p)
4523801552

>>> p = []
>>> id(p)
4527080640
>>> p.append(11)
>>> id(p)
4527080640

 

 

root cause

Parameter Default Python function is bound at compile stage. (Write code to define.)

 

The following is a from the Python Common Gotchas reasons explained extract:

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.

It can be seen:

  1. When you run the code, when you run the function definitions, default parameters of expression was performed. 
  2. When the function call, default expression argument does not run again. ⚠️ this point and Ruby are completely different.
  3. This indicates that if the default parameters, the object points to a constant, for example, L = 1. So when the function is called, the re-assignment in vivo function L, L is in fact a new pointer is a new memory address. The original default parameters L itself and points to the memory address of the function definition is already stored in the beginning of the compile-time. Can __default__ view.
  4. If the default is a variable parameter points to an object, such as List, then L.append (a) modification of a variable object itself, L at the memory address remain unchanged. So every time the function is called the default object parameters are out of this memory address.

Third, modifying the above example:

 

def f(a, L = 1):
    L = a
    print(id(L))
    return L

print("self",id(f.__defaults__[0]))
print(f(1))
print("self",id(f.__defaults__[0]))
print(f(33))
print("self",id(f.__defaults__[0]))

#运行结果:
self 4353170064
4353170064
1
self 4353170064
4353171088
33
self 4353170064

The default parameters L, bound at compile stage, stored in __default__. L = a function in vivo expression, a new variable is generated. L is the return of new variables, and nothing to default parameters.

 

Fourth, or the above example, the default parameters of the type of change it to a mutable object list:

def f(a, L = []):
    L.append(a)
    print(id(L))
    return L
# L = f(1)
print("self",id(f.__defaults__[0]))
print(f(1))
print("self",id(f.__defaults__[0]))
print(f(33))
print("self",id(f.__defaults__[0]))
# Return results 
Self 4337586048 
4337586048 
[ . 1 ] 
Self 4337586048 
4337586048 
[ . 1, 33 is ] 
Self 4337586048

By id number shows that returns the default parameter itself.

 

How to avoid this trap unnecessary trouble

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

 

Why such a design Python

 StackOverflow  debate on a lot.

 

Ruby is no reason why this issue, I think it's because Ruby's def keyword defines a closed scope, any data to be passed to the method within the parameters, can be used.

And the role of Ruby ratio, Python argument is greatly weakened. Python appear later in Ruby, founder of Ruby's certainly a reference design. Abandoned this design, select a function similar to the way the javascript. def defined functions can be performed when receiving the variable external scope.

The idea that:

For the implementation of the Python compiler consideration is an internal function of an object. The default parameter value is a property of the object. In any other language, object properties are bound to do when the object is created. Therefore, the function parameter bind a default is not surprising at compile time.

 

This reference: http://cenalulu.github.io/python/default-mutable-arguments/#toc1  , and adding their own understanding. Welcome to reprint!

 

Guess you like

Origin www.cnblogs.com/chentianwei/p/11963383.html