我可以使用class属性作为实例方法的默认值吗?

时间:2010-10-28 09:46:31

标签: python

我想使用class属性作为我的类__init__方法的一个参数的默认值。但是,这个结构引发了NameError异常,我不明白为什么:

class MyClass():
    __DefaultName = 'DefaultName'
    def __init__(self, name = MyClass.__DefaultName):
        self.name = name

为什么这会失败,有没有办法做到这一点?

2 个答案:

答案 0 :(得分:28)

那是因为,根据documentation

  

在函数定义时计算默认参数值   执行。这意味着   表达式被评估一次,当时   函数已定义

定义__init__()时,MyClass的定义不完整,因为它仍在解析中,因此您无法引用MyClass.__DefaultName。解决此问题的一种方法是将特殊唯一值传递给__init__(),例如None

def __init__(self, name=None):
    if name is None:
        name = MyClass.__DefaultName
    # ...

答案 1 :(得分:22)

在执行不同位代码时,要记住Python的一个重要事项是以及在class和def语句这一事实>见过,不仅仅是为了以后存储起来。使用def它会更容易理解,因为唯一要执行的是()之间的任何内容 - 所以在上面的代码中

def __init__( SELF, name = MyClass.__DefaultName ):

当Python看到MyClass.__DefaultName时,它首先尝试在local命名空间中找到它,然后是模块(又名global)命名空间,最后在builtins中找到它。

执行local语句时class命名空间是什么?这是有趣的部分 - 它将成为class命名空间,但目前它是匿名的 - 所以你不能通过名称引用它(在你的代码中也称为MyClass)但是你可以直接引用已定义的任何内容......以及已定义的内容?在您的课程示例中只有一件事 - __DefaultName。所以你的__init__应该是这样的:

def __init__( SELF, name=__DefaultName ):

请注意,您以后无法更改MyClass._MyClass__DefaultName并在新实例中显示这些更改。为什么?因为__init__ def只执行一次,并且当前存储的值__DefaultName已被存储并且将始终使用 - 除非您在创建新实例时直接指定新值:

my_instance = MyClass(name='new name')