为啥通过 python 默认变量初始化变量会在对象实例化过程中保持状态?
Posted
技术标签:
【中文标题】为啥通过 python 默认变量初始化变量会在对象实例化过程中保持状态?【英文标题】:Why does initializing a variable via a python default variable keep state across object instantiation?为什么通过 python 默认变量初始化变量会在对象实例化过程中保持状态? 【发布时间】:2011-04-22 16:08:31 【问题描述】:我今天遇到了一个有趣的 python 错误,其中反复实例化一个类似乎处于保持状态。在稍后的实例化调用中,该变量已经定义。
我将问题归结为以下类/shell 交互。我意识到这不是初始化类变量的最佳方法,但它肯定不应该这样。这是一个真正的错误还是这是一个“功能”? :D
tester.py:
类测试器(): def __init__(self): self.mydict = self.test() 定义测试(自我,out = ): 键=“键” 对于 ['a','b','c','d'] 中的 i: 如果输入输出: 出[键] += ','+i 别的: 出[键] = 我 返回Python 提示:
Python 2.6.6(r266:84292,2010 年 10 月 6 日,00:44:09) [GCC 4.2.1 (Apple Inc. build 5664)] 在达尔文 >>> 导入测试仪 >>> t = tester.Tester() >>> 打印 t.mydict 'key': 'a,b,c,d' >>> t2 = tester.Tester() >>> 打印 t2.mydict 'key': 'a,b,c,d,a,b,c,d'【问题讨论】:
它会不会将out
解释为一个全局变量,从而在您调用test
时不断添加它?
复制:***.com/questions/1132941/…
"Least Astonishment" and the Mutable Default Argument的可能重复
【参考方案1】:
这是一个几乎所有 Python 用户都会遇到一次或两次的功能。主要用于缓存等以避免重复冗长的计算(实际上是简单的记忆),尽管我相信人们已经找到了它的其他用途。
原因是def
语句只执行一次,也就是定义函数的时候。因此初始化器值只被创建一次。对于像列表或字典这样的引用类型(相对于不能更改的不可变类型),这最终会成为一个可见且令人惊讶的陷阱,而对于值类型,它会被忽视。
通常,人们会这样处理它:
def test(a=None):
if a is None:
a =
# ... etc.
【讨论】:
你很好的解释。我想添加另一行。 function 是 python 中的一个对象,当我们第一次调用 function 对象时,会创建一个对象,之后我们会重用同一个对象。您可以通过在每次通话后打印 id(Test) 来确认。您将获得相同的函数对象 ID,这意味着只有一个对象在共享。【参考方案2】:一般来说,默认方法参数不应该是可变的。而是这样做:
def test(self, out=None):
out = out or
# other code goes here.
请参阅这些链接,了解有关为什么这是必要的以及为什么它是 python 语言的“功能”而不是错误的更多详细信息。
"Least Astonishment" and the Mutable Default Argument http://effbot.org/zone/default-values.htm【讨论】:
out = out or
不仅有一种腐朽的味道,而且如果调用者传入他们自己的空映射对象,也会失败。 if out is None: out =
更可取。【参考方案3】:
您正在修改方法中函数关键字参数out
的值。
This blog post 简洁解释:
默认参数中的表达式在定义函数时计算,不在调用时计算。
函数是在创建类时定义的,而不是针对每个实例。如果你像这样修改它,问题就会消失:
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
【讨论】:
以上是关于为啥通过 python 默认变量初始化变量会在对象实例化过程中保持状态?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Python 类初始化变量不能用于包导入中的类实例对象,但否则?
JS全局变量是全局对象的属性,函数局部变量为啥就不是函数的属性呢?