Python 在外部类范围中找不到变量

Python 在外部类范围中找不到变量,python,class,namespaces,Python,Class,Namespaces,我有以下代码: class Attributes(object): class __metaclass__(type): def __init__(self, cls_name, cls_bases, cls_dict): # super(Attributes.__metaclass__, self) # NameError: global name 'Attributes' is not defined super(__m

我有以下代码:

class Attributes(object):
    class __metaclass__(type):
        def __init__(self, cls_name, cls_bases, cls_dict):
            # super(Attributes.__metaclass__, self) # NameError: global name 'Attributes' is not defined
            super(__metaclass__, self).__init__(
                cls_name, cls_bases, cls_dict)
给予

为什么在外部作用域中找不到
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

super(Attributes.__metaclass__, self).__init__(cls_name, cls_bases, cls_dict)

看来答案是这样的:

方法的外部作用域不是类主体,而是包含类或模块的外部函数

这就是为什么在这种情况下

class Test():
    attr_1 = 'smth'
    def a_method(self):
        attr_1  # not visible on this line
attr\u 1
在方法
Test.a\u方法中不可见

解决方案是在全局级别定义元类:

class AttributesMeta(type):
    def __init__(self, cls_name, cls_bases, cls_dict):
        super(__metaclass__, self).__init__(
            cls_name, cls_bases, cls_dict)

class Attributes(object):
    __metaclass__ = AttributesMeta

创建类时,只有其名称可见。在类创建完成之前,它的内容还不存在。因此,类中的部分在创建期间无法访问类的任何字段。因此,您需要使用完全限定名来表示您希望访问类的字段

您当前正在创建一个类
SimpleModel
,同时创建一个类
属性
,同时创建一个类
\uuuu元类
。因为在执行此操作时,类
SimpleModel
还不存在,所以方法
\uuuu init\uuuu
还不是任何现有内容的一部分。它首先被创建,然后,稍后将成为类的一部分。因此,它无法知道标识符
\uuuuu元类\uuuuu
。由于
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


这就是为什么此时在您的作用域中没有
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,所以我可以快速运行它,看看是否可以重现这个问题?我尝试重现这个问题,结果发现类中不能有调用super的init方法的类。这不仅仅是第三级继承,即使您尝试在
属性
中调用
超级
,也不会起作用。您需要调用
SimpleModel.Attributes
来获取它。感谢您的解决方案。我做了一个不同的变通方法,将有问题的类放在模块的顶层。我简化了问题中的示例。如果您尝试使用
super(Attributes.\uuuuu元类\uuuuuuuuuu,self)
-您会得到
名称错误:未定义全局名称“Attributes”
。所以你的解决方案不起作用,沃鲁克是对的。创建元类的第一个实例时,
属性还不存在:首先创建元类,然后在外部类完成之前立即(自动)创建一个实例。在
\uuuu init\uuuu
内部,不仅已经创建了类,但它的实例也被创建并作为
self
传递。在本例中,
self
是一个类,它是它的元类的实例。@warwaruk:你说的是运行时,我说的是编译时(也就是说,如果你真的能在Python中将两者分开的话)。当编译
\uuuu init\uuuu
时,类还不存在。这就是Python不允许在不完全限定名称的情况下引用本地类的根本原因。问题:我是否应该在回答中详细说明这一方面?(我(希望)在第二段中添加了一个明确的句子。)注意,我谈论的是“创建类”,而不是“创建实例”…我在运行时得到了引用的异常,因为在
属性
类被完全定义之后,它是通过调用
属性创建的。创建类意味着创建其元类的实例。我想你错了。我想你可能会被这个结构弄糊涂了:
class\uuuu元类(AttributesMeta)
,它实际上等于
\uu元类\uuuuu=另一个attributemetaclass
,其中,
另一个AttributeMetaClass
将在前面使用问题中相同的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。当然,请参见在运行时获得异常。但因为在编译时标识符是未知的。在我的回答中,有没有关于如何使这一点更清楚的建议?
class AttributesMeta(type):
    def __init__(self, cls_name, cls_bases, cls_dict):
        super(__metaclass__, self).__init__(
            cls_name, cls_bases, cls_dict)

class Attributes(object):
    __metaclass__ = AttributesMeta