Python中空元组的潜在用途

2024-10-02 00:33:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Python中讨论了类级别变量的风险,我认为列表作为类级别变量的风险可以通过元组(例如空元组)来解决。在

采取:

class BaseClass(object):
    default_sth = []

    def foo(self):
       for sth in self.default_sth:
           pass

这是有风险的,因为:

^{pr2}$

使用None而不是空元组(tuple()?)可能反而很危险,因为它在迭代时失败。在

由于不变性,我认为这是一个很好的选择,但我认为我在任何地方都没见过有人谈论这个问题。你认为这种推理有什么缺陷吗?是Python吗?在


Tags: inselfdefault列表forobjectfoodef
3条回答

您将类变量与实例变量混淆(这很容易做到,因为在没有初始化的实例变量的情况下,查找会找到类变量)。在本例中,您已经显式地说default_sth是一个类变量,而您的意思是为实例变量设置一个默认值。改用这个:

class BaseClass(object):
    def __init__(self, sth=None):
        if sth is None:
            sth = []

    def foo(self):
       for sth in self.sth:
           pass

您可能会对使用“硬编码”默认值有点犹豫,但您只是通过尝试为默认值使用单独的名称来增加详细程度。只需注释并记录您的__init__方法,以指示sth是什么,如果不是,它的默认值应该是什么 传递其他值。除非你有充分的理由,否则不要试图让默认设置本身可配置。在

就不变性而言,只有元组是不可变的,而不是引用它的名称。没有什么能阻止别人使用你的原始代码

^{pr2}$

尽管要从default_sth开始创建元组,但您还是回到了开始的地方。在

我认为使用元组而不是列表的问题是人们通常选择使用列表,因为他们实际上想要列表语义;你不能附加到一个元组,对它进行适当的排序,从中删除项等等。如果你不想让你的类级列表属性与子类共享,子类只能创建自己的副本:

from copy import deepcopy

class SubClass(BaseClass):
    default_sth = deepcopy(BaseClass.default_sth)  # now SubClass has its own copy.

然后您的示例将输出[],这是您希望的行为。如果您在BaseClass中使用一个元组,您的示例将抛出一个AttributeError(因为它试图在一个元组上调用append),并且代码需要更改为这个值来执行append的等效操作:

^{pr2}$

这样写起来有点痛苦,而且效率不高,因为要从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

相关问题 更多 >

    热门问题