I have a class A
:
class A(object):
a = 'a'
def __init__(self):
self.b = 'b'
def foo(self):
print A.a
print self.b
I just wondering how to construct this class by meta programming.
I have tried:
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()
It's works, but still have some problem, that is, I have to use A_CLASS
as the name of the class, if I use B_CLASS
, it doesn't work anymore:
B_CLASS = type('A_CLASS',(object,),{'a':'a','__init__':Init,'foo':Foo})
myObj = B_CLASS()
myObj.foo() #Error ocurred
If there is a way to construct such a class, where the name of the variable 'X_CLASS' is not relevant at all?
The problem is that you use the name A_CLASS
literally in Foo
. You can always get the runtime class of the current object with self.__class__
.
def Foo(self):
print self.__class__.a
print self.b
Your error occurs because Foo
unconditionally references A_CLASS
, but you bound the class to a global name B_CLASS
. This is going to be a problem in other circumstances ( pickle
relies on the class name matching the name it was bound to in the defining module), but for this limited case it's fixable. Instead of referring to A_CLASS.a
directly, refer to it in terms of self
:
def Foo(self):
print self.a
print self.b
self
will look for class attributes if no instance attribute of that name exists. If you want to be 100% sure it came from the class, not the instance, you can instead define it as:
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
which looks up the class, then gets the attribute from the class, bypassing instance attributes.
In an inheritance hierarchy, this might be wrong. If there is a A_CHILD
class with a different a
class attribute, calling Foo
on it will get the child's attribute. But that's the price of violating the rules; if you give a class the name A_CLASS
and bind it to the name B_CLASS
, you can't refer to it by the name A_CLASS
for lookup (because there is no part of your program that has that binding).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.