如何在python元编程中使用实例方法?

时间:2018-02-06 03:50:35

标签: python metaprogramming metaclass

我有一个班级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'的名称根本不相关?

2 个答案:

答案 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引用它进行查找(因为您的程序没有任何部分)有那种约束力。)