python使用变量需要初始化吗_关于参数:为什么通过python默认变量初始化变量会在对象实例化过程中保持状态?...

我今天遇到了一个有趣的python bug,在这个bug中,反复实例化一个类似乎处于保持状态。在以后的实例化调用中,已经定义了变量。

我将问题归结为以下类/shell交互。我认识到这不是初始化类变量的最佳方法,但它肯定不应该这样做。这是一个真正的bug还是一个"特性"?D

测试:

class Tester():

def __init__(self):

self.mydict = self.test()

def test(self,out={}):

key ="key"

for i in ['a','b','c','d']:

if key in out:

out[key] += ','+i

else:

out[key] = i

return out

Python提示:

Python 2.6.6 (r266:84292, Oct  6 2010, 00:44:09)

[GCC 4.2.1 (Apple Inc. build 5664)] on darwin

>>> import tester

>>> t = tester.Tester()

>>> print t.mydict

{'key': 'a,b,c,d'}

>>> t2 = tester.Tester()

>>> print t2.mydict

{'key': 'a,b,c,d,a,b,c,d'}

它是否可以将out解释为一个全局变量,从而在调用test时不断地向其添加?

dupe:stackoverflow.com/questions/1132941/…

"最小惊异"和可变默认参数的可能重复

这是几乎所有的Python用户都会遇到的一个特性。主要用于缓存等,以避免重复冗长的计算(实际上是简单的记忆化),尽管我确信人们已经找到了它的其他用途。

这样做的原因是,def语句只执行一次,即在定义函数时执行一次。因此,初始值设定项值只创建一次。对于像列表或字典这样的引用类型(与不能更改的不可变类型相反),这最终会成为一个可见的、令人惊讶的陷阱,而对于值类型,则不会被注意到。

通常情况下,人们都是这样工作的:

def test(a=None):

if a is None:

a = {}

# ... etc.

你解释得很好。我想再加一行。函数是python中的一个对象,当我们第一次调用函数对象时,我们将重用同一个对象。您可以在每次通话后打印ID(测试)进行确认。您将获得相同的函数对象ID,这意味着只有一个对象正在共享。

通常,默认方法参数不应是可变的。而是这样做:

def test(self, out=None):

out = out or {}

# other code goes here.

请参阅这些链接,了解更多关于为什么需要这样做以及为什么它是Python语言的"特性"而不是bug的详细信息。

"最小惊异"和可变的默认参数

http://effbot.org/zone/default-values.htm(http://effbot.org/zone/default-values.htm)

out = out or {}不仅具有Perlish特性,而且如果调用者传入自己的空映射对象,它也会失败。最好是if out is None: out = {}。

您正在修改方法中的函数关键字参数out的值。

这篇博文简洁地解释了这一点:

expressions in default arguments are calculated when the function is defined, not when it’s called.

函数是在创建类时定义的,不是为每个实例定义的。如果您这样修改它,问题就消失了:

def test(self,out=None):

if out is None:

out = {}

key ="key"

for i in ['a','b','c','d']:

if key in out:

out[key] += ','+i

else:

out[key] = i

return out

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值