为啥我不能在 python 中访问这个类成员?

Posted

技术标签:

【中文标题】为啥我不能在 python 中访问这个类成员?【英文标题】: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)方法来做这样的事情。

【问题讨论】:

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

【讨论】:

或者像***.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

【讨论】:

以上是关于为啥我不能在 python 中访问这个类成员?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能访问静态多态派生类中的受保护成员?

为啥我不能访问指向数组中成员函数的指针?

为啥我不能从不同命名空间中的朋友类更改类的私有成员?

为啥嵌套的子类可以访问其父类的私有成员,而孙子却不能?

为啥我不能访问派生构造函数的成员初始化列表中继承的受保护字段?

在Java中,如果这样写,为啥私有数据成员可以在类外部访问? [复制]