我在Python中讨论了类级别变量的风险,我认为列表作为类级别变量的风险可以通过元组(例如空元组)来解决。在
采取:
class BaseClass(object):
default_sth = []
def foo(self):
for sth in self.default_sth:
pass
这是有风险的,因为:
^{pr2}$使用None
而不是空元组(tuple()
?)可能反而很危险,因为它在迭代时失败。在
由于不变性,我认为这是一个很好的选择,但我认为我在任何地方都没见过有人谈论这个问题。你认为这种推理有什么缺陷吗?是Python吗?在
您将类变量与实例变量混淆(这很容易做到,因为在没有初始化的实例变量的情况下,查找会找到类变量)。在本例中,您已经显式地说
default_sth
是一个类变量,而您的意思是为实例变量设置一个默认值。改用这个:您可能会对使用“硬编码”默认值有点犹豫,但您只是通过尝试为默认值使用单独的名称来增加详细程度。只需注释并记录您的
__init__
方法,以指示sth
是什么,如果不是,它的默认值应该是什么 传递其他值。除非你有充分的理由,否则不要试图让默认设置本身可配置。在就不变性而言,只有元组是不可变的,而不是引用它的名称。没有什么能阻止别人使用你的原始代码
^{pr2}$尽管要从
default_sth
开始创建元组,但您还是回到了开始的地方。在我认为使用元组而不是列表的问题是人们通常选择使用列表,因为他们实际上想要列表语义;你不能附加到一个元组,对它进行适当的排序,从中删除项等等。如果你不想让你的类级列表属性与子类共享,子类只能创建自己的副本:
然后您的示例将输出
^{pr2}$[]
,这是您希望的行为。如果您在BaseClass
中使用一个元组,您的示例将抛出一个AttributeError
(因为它试图在一个元组上调用append
),并且代码需要更改为这个值来执行append
的等效操作:这样写起来有点痛苦,而且效率不高,因为要从tuple->;list->;tuple进行大量复制来转换。在
可变的默认变量在其他方面如此漂亮的Python中是众所周知的垃圾。在
例如
http://eli.thegreenplace.net/2009/01/16/python-insight-beware-of-mutable-default-values-for-arguments/
"Least Astonishment" and the Mutable Default Argument
http://pythonconquerstheuniverse.wordpress.com/2012/02/15/mutable-default-arguments/
解决方案包括
初始化
__init__
-不要使用类级别的变量,除非你真正指的是全局变量传入
None
,并在第一次访问时将其转换为list相关问题 更多 >
编程相关推荐