关于python 默认参数的疑问
PHP中文网
PHP中文网 2017-04-17 13:37:41
0
5
889

python文档中关于默认参数是这样说的:

Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call.

因此,如下代码:

def function(data=[]):
    print id(data), data
    data.append(1)

for i in range(3):
    function()

输出结果为:

4462873272 []
4462873272 [1]
4462873272 [1, 1]

一切正像文档中说的那样,data只计算一次,之后的调用返回的是已经计算出来的值(因此,id(data)没有变化,每次append均针对同一个data)

但是我们带参数调用function时,即:

for i in range(3):
    function([])

输出结果为:

4462872984 []
4462872984 []
4462872984 []

data的值是符合预期的,但是三次调用function,id(data)的值竟然也一样,这个是为什么呢?带参数传递时,每次调用都应该是新建data的吧。

PHP中文网
PHP中文网

认证0级讲师

répondre à tous(5)
Ty80

认真读文档啊:https://docs.python.org/2/library/functions.html#id 。
Because:

Two objects with non-overlapping lifetimes may have the same id() value.

CPython中id的实现概念上相当于对象在内存中的地址。那请看这段代码:

id([])
# then it destory
id([])
# then its memory reused

前后是两个不同的list对象,但既然前面一个对象用完就被销毁掉了,那后面的一个list就可能重用相同的内存空间,所以id返回的地址就是一样的了。

Peter_Zhu

LZ请注意常量与变量的区别, 你想要个不同的id, 得用list()。

巴扎黑

虽然不明白最后到底有没有回答到问题深处, 但如果这个答案能帮助有的同学对参数的疑惑 也是好的.

前一阵子我也是刚学python, 看到关于默认参数列表的一部分, 说一下我的理解.

当调用函数f() 连续三次时,

第一次 f() 会找到默认参数 data = []
而且它在内存中中的地址是能通过 类似 'f.data' 寻址的.
接下来再次调用 f() 会重复以上操作, 因为没有输入一个新的参数, 会默认还是找到之前的data作为此次参数列表.

def f(data = []):
    data.append("end")
    print data

f()

执行前 data = []
执行后 默认参数变为 data =['end']

f()

重复上次操作 这里data 可以理解为该函数的一个成员变量


另外 也可以调用 f.defaults 这个属性来查看函数f当前情况的默认参数是什么

比如 定义完f后,

 # 定义完f后的默认参数
print f.__defaults__
#>>([],)
# f() 执行后的默认参数
print f.__defaults__
#>>(['end'],)

所以默认参数在前后几次 f()执行过程中是可变的.

而如果调用f([]) 的话 是不会对默认参数产生影响的,

print f.__defaults__
f([])
print f.__defaults__
f([])
print f.__defaults__

如果有兴趣还可以尝试一下 对
f(data = [] ) 进行迭代 :)

可以参考这里 觉得讲的很清楚 Python 中函数的参数

左手右手慢动作

这个问题是这样子的...
这是算是python比较高级的内容了吧..初学者基本上都会碰到这个问题


好了,正文开始

函数的内省导致了,你的参数是函数类型的一个属性(虽然没办法用.来访问).
这也就是意味着,你在定义函数的时候,你的参数已经成了这个函数对象的一部分了..类似于:

class cls():
    A = []

a = cls()
b = cls()
a.A.append("a")
print b.A

你可以发现有刚刚的"a"被打印出来了..
函数这边也是一样的.定义的参数属性是共享的
但是以上规则仅仅针对于可变数据类型类型,比如列表
因为不可变数据类型不是在当前这个内存块里面修改的...而是指向了另外一个内存块..


扩展阅读:

两个python特性:

1. python的动态类型问题:

动态类型的意思是:你的变量只是一个类似于指针的东西.只不过他可以随便乱指...他指向的是一个类型.这个类型可以是整型,字符串,类等等.

你的一个变量可以更换指向的类型.比如:a = 1a指向的是一个整型类型.这个整型类型的值是1(当然还有其他一些组成部分,比如还有count和类型声明等等)
但是当你从新指向的时候,比如:a = "hello world",那么发生的事情是,a这个变量指向了一个字符串类型,而之前1这个整型发生的变化是count-1,等count为0了内存才被回收.
这就是传说中的动态类型

2. 函数的内省

函数在python中也是类型.
比如你

def foo(a, b):
    pass

那么就是生成了一个函数类型,赋值给foo这个变量了..
而这个类型中所有东西都可以通过域操作符 . 来操作.


伊谢尔伦

同意ls

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal