简体   繁体   中英

How to use instance methods in python meta programming?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM