【问题标题】:Why can I not access this class member in python?为什么我不能在 python 中访问这个类成员?
【发布时间】:2011-01-11 08:49:20
【问题描述】:

我有以下代码

class Transcription(object):
    WORD = 0
    PHONE = 1
    STATE = 2

    def __init__(self):
        self.transcriptions = []

    def align_transcription(self,model,target=Transcription.PHONE):
        pass

这里的重要部分是我希望有一个类成员作为变量的默认值。然而,这会产生以下错误:

NameError: name 'Transcription' is not defined

为什么这是不可能的,什么是正确的(pythonic)方法来做这样的事情。

【问题讨论】:

  • 正确的方法?很难说,你想做什么?为什么要将对象的类传递给该对象的函数?我看不出你想在这里做什么。
  • 他想使用一个作用域为类的常量作为方法参数的默认值。
  • 没错。我的错。语法着色使我蒙蔽了双眼。 :)

标签: python class-members


【解决方案1】:

您无法访问它,因为在 def 语句运行时未定义 Transcription

 def align_transcription(self,model,target=PHONE):
        pass

会成功的。 PHONE 名称在命名空间中可用,class 语句完成执行后将成为Transcription 类。

其工作方式是class 是一个实际运行的语句。当 Python 遇到一个类语句时,它会进入一个新的本地范围并执行在 class 语句下缩进的所有内容,就好像它是一个函数一样。然后它将生成的命名空间、类的名称和基类的元组传递给 metaclass,默认情况下为 type。元类返回一个自身的实例,它是实际的类。当def 语句执行时,这些都没有发生。

声明

class Foo(object):
    a = 1
    def foo(self):
        print self.a

创建一个命名空间ns = {'a': 1, 'foo': foo}然后执行

Foo = type('Foo', (object,), ns)

这相当于

def foo(self):
    print self.a

Foo = type('Foo', (object,), {'a': 1, 'foo': foo})

您可以清楚地看到在定义 foo 时未定义 Foo,因此 Foo.a 没有意义。

【讨论】:

    【解决方案2】:

    直到定义结束,类才与其名称相关联。

    我写这个的方式(我不能保证它是 Pythonic)是:

    class Transcription(object):
        WORD = 1   # zero won't work below... need to change the value
        PHONE = 2
        STATE = 3
    
        def align_transcription(self, model, target=None):
            target = target or Transcription.PHONE
            # or
            if target is None: target = Transcription.PHONE
    

    或者,将PHONE 设置为零而不是WORD 也可以。无论常量的值如何,if 语句都将起作用,但or 将用PHONE 替换零值。

    其他选项是在另一个类中定义常量或在类外绑定align_transcription 方法:

    class Transcription(object):
        WORD = 0
        PHONE = 1
        STATE = 2
    
    def _unbound_align_transcription(self, model, target=Transcription.PHONE):
        pass
    
    Transcription.align_transcription = _unbound_align_transcription
    

    【讨论】:

    • 或者像stackoverflow.com/questions/4655745/…那样做......我知道,只是没有立即想到。
    • 我认为像“类对象在其定义完成之前不可用”这样的简单响应也可以。
    • 这是真的,除了在类are 中定义的值可用。诀窍是绑定函数 signaturesdef 行)在定义点位于类范围内,而绑定函数 code 不在,需要使用要消除歧义的类名。
    【解决方案3】:

    定义 align_transcription 方法时 Transaction 类还不存在,但 PHONE 在范围内可用。 所以,你可以这样做:

    class Transcription(object):
        WORD = 0
        PHONE = 1
        STATE = 2
    
    def __init__(self):
        self.transcriptions = []
    
    def align_transcription(self,model,target=PHONE):
        pass
    

    如果您打算在子类或实例中覆盖 PHONE,则使用 target=None 默认值:

    def align_transcription(self,model,target=None):
        if target is None:
            target = self.PHONE
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 2012-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      相关资源
      最近更新 更多