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