我有一个班级A
:
class A(object):
a = 'a'
def __init__(self):
self.b = 'b'
def foo(self):
print A.a
print self.b
我只是想知道如何通过元编程来构造这个类。
我试过了:
def Init(self):
self.b = 'b'
def Foo(self):
print A_CLASS.a
print self.b
A_CLASS = type('A_CLASS',(object,),{'a':'a','__init__':Init,'foo':Foo})
myObj = A_CLASS()
myObj.foo()
它有效,但仍然有一些问题,也就是说,我必须使用A_CLASS
作为类的名称,如果我使用B_CLASS
,它将不再起作用:
B_CLASS = type('A_CLASS',(object,),{'a':'a','__init__':Init,'foo':Foo})
myObj = B_CLASS()
myObj.foo() #Error ocurred
如果有办法构建这样一个类,那么变量'X_CLASS'的名称根本不相关?
答案 0 :(得分:2)
问题是您在A_CLASS
中使用名称Foo
。您始终可以使用self.__class__
获取当前对象的运行时类。
def Foo(self):
print self.__class__.a
print self.b
答案 1 :(得分:2)
您的错误发生是因为Foo
无条件地引用A_CLASS
,但您将该类绑定到全局名称B_CLASS
。这在其他情况下会成为一个问题(pickle
依赖于与定义模块中绑定的名称相匹配的类名称),但对于这种有限的情况,它是可修复的。不是直接引用A_CLASS.a
,而是根据self
:
def Foo(self):
print self.a
print self.b
如果不存在该名称的实例属性, self
将查找类属性。如果你想100%确定它来自类,而不是实例,你可以将它定义为:
def Foo(self):
# New-style class only, but safe against weirdness like redefining __class__
print type(self).a
# Old-style class, and vast majority of non-pathological new-style classes
print self.__class__.a
print self.b
查找类,然后从类中获取属性,绕过实例属性。
在继承层次结构中,这可能是错误的。如果A_CHILD
类具有不同的a
类属性,则在其上调用Foo
将获取子属性。但这是违反规则的代价;如果您为类命名A_CLASS
并将其绑定到名称B_CLASS
,则无法通过名称A_CLASS
引用它进行查找(因为您的程序没有任何部分)有那种约束力。)