# Python函数参数默认值的陷阱和原理深究

## 陷阱重现

Python

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Python 2.7.9 (default, Dec 19 2014, 06:05:48) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang–600.0.56)] on darwin Type “help”, “copyright”, “credits” or “license” for more information. >>> def generate_new_list_with(my_list=[], element=None): ...     my_list.append(element) ...     return my_list ... >>> list_1 = generate_new_list_with(element=1) >>> list_1 [1] >>> list_2 = generate_new_list_with(element=2) >>> list_2 [1, 2] >>>

#### 准备知识：Python变量的实质

Python变量区别于其他编程语言的申明&赋值方式，采用的是创建&指向的类似于指针的方式实现的。即Python中的变量实际上是对值或者对象的一个指针（简单的说他们是值得一个名字）。我们来看一个例子。

Python

 1 2 p = 1 p = p+1

## 函数参数默认值陷阱的根本原因

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.

Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. For example, the following function accumulates the arguments passed to it on subsequent calls:

## 如何避免这个陷阱带来不必要麻烦

Python

 1 2 3 4 5 def generate_new_list_with(my_list=None, element=None):     if my_list is None:         my_list = []     my_list.append(element)     return my_list

## 为什么Python要这么设计

Actually, this is not a design flaw, and it is not because of internals, or performance.

It comes simply from the fact that functions in Python are first-class objects, and not only a piece of code.

As soon as you get to think into this way, then it completely makes sense: a function is an object being evaluated on its definition; default parameters are kind of “member data” and therefore their state may change from one call to the other – exactly as in any other object.

In any case, Effbot has a very nice explanation of the reasons for this behavior in Default Parameter Values in Python.

I found it very clear, and I really suggest reading it for a better knowledge of how function objects work.

This is not a design flaw. It is a design decision; perhaps a bad one, but not an accident. The state thing is just like any other closure: a closure is not a function, and a function with mutable default argument is not a function.

> Sorry, but anything considered “The biggest WTF in Python” is most definitely a design flaw. This is a source of bugs for everyone at some point, because no one expects that behavior at first – which means it should not have been designed that way to begin with.

The phrases “this is not generally what was intended” and “a way around this is” smell like they’re documenting a design flaw.

1