Python 手册的 Tutorial.pdf 中 “ 4.7.1 参数默认值” 有如下的例子:
def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print(f(3))
这将打印出
[1] [1, 2] [1, 2, 3]
如果你不想要在后续调用之间共享默认值,你可以这样写这个函数:
def f(a, L=None): if L is None: L = [] L.append(a) return L
我家高中生刚学编程,把程序改为如下进行测试,问我 f3 和 f1 的 L 到底差别在哪儿,把我搞懵了,哪个能给出一个简单、初学编程的人听得懂的解释(我只能给他解释 f1 的 L 是可变对象,f3 的 L 是不可变对象?)
def f1(a, L=[]): print("id(L) = ", id(L)) print("L = ", L) print() L.append(a) return L def f3(a, L=None): print("id(L) = ", id(L)) print("L = ", L) if L is None: # 为何每次成立? L=[] print("id(L) = ", id(L)) print() L.append(a) return L if __name__ == "__main__": f1(1) f1(2) f1(3) print('-'*40) f3(1) f3(2) f3(3)
执行时打印出:
id(L) = 2405815737608 L = [] id(L) = 2405815737608 L = [1] id(L) = 2405815737608 L = [1, 2] ---------------------------------------- id(L) = 1983976656 L = None id(L) = 2405815759368 id(L) = 1983976656 L = None id(L) = 2405815759368 id(L) = 1983976656 L = None id(L) = 2405815759368
1 densuc 2019-06-16 10:32:47 +08:00 via iPhone 用的 2.7 版本?好像 2 和 3 版本的变量带入是不同的。。。 |
![]() | 2 BingoXuan 2019-06-16 10:37:52 +08:00 via Android ![]() 很明显就是函数定义时候这个默认变量就已经初始化了,但调用函数时候,就算重新赋值,也不会修改原变量。也就是函数和其默认参数的作用域是一样。就像你定义一个变量后,再定义函数并传入。你可以用 inspect 模块看一下,你会发现 f1 的默认参数值都会变。其实这个是个坑,我记得某家公司就是被这个特性( bug )搞挂了。 |
3 youngce 2019-06-16 10:43:18 +08:00 ```python def f(a, L=[]): L.append(a) return L print(f(1),f.__defaults__) # [1] ([1],) print(f(2),f.__defaults__) # [1, 2] ([1, 2],) print(f(3),f.__defaults__) # [1, 2, 3] ([1, 2, 3],) ``` 不知道有没有帮助,总之 python 里面没有原生的函数,都是一堆对象 |
4 princelai 2019-06-16 10:44:51 +08:00 via Android ![]() 等号左边的 L 存储的是一个栈地址,当等号右边是可变对象是,赋值为一个可变的堆对象地址,也就是指针,当等号右边是个不可变常量时,存储该值的地址。Python 的参数传递是引用传递,给个可变对象意味着这是外部对象的指针,给个不可变对象,然后你又在内部从新赋值为[],L 一直是内部变量 |
5 azh7138m 2019-06-16 10:44:56 +08:00 f1 每次的默认参数都是同一个 '[]' f3 每次的默认参数都是同一个 'None' > Python ’ s default arguments are evaluated once when the function is defined, not each time the function is called |
![]() | 6 Xs0ul 2019-06-16 10:49:09 +08:00 楼主想问的是为什么 f3 运行得到的 list 的 id 还是一样的? 你试试 l1 = f3(1) l2 = f3(2) l3 = f3(3) 或者 f3(1) a = [] print(id(a)) f3(2) f3(3) f1 里一样是因为相当于提前创建了一个 list,把这个 list 作为默认参数,所以每次都是这一个 f3 里是内部创建了一个新的 list,按道理每次 id 不一定一样。但是因为生成的 list 没被接收,相当于已经废弃,第二次生成的时候或许是重复利用了 /生成了同样的一个 |
![]() | 7 Takamine 2019-06-16 19:06:15 +08:00 via Android 最好不要用可变类型做入参,很容易有坑。(ò ó) |