代码之家  ›  专栏  ›  技术社区  ›  spring cc

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

  •  3
  • spring cc  · 技术社区  · 6 年前

    我有课 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\u class”的名称在哪里根本不相关?

    2 回复  |  直到 6 年前
        1
  •  2
  •   ShadowRanger    6 年前

    发生错误的原因是 Foo 无条件引用 A_CLASS ,但将类绑定到全局名称 B_CLASS . 在其他情况下,这将是一个问题( pickle 依赖于与它在定义模块中绑定到的名称匹配的类名),但对于这种有限的情况,它是可以修复的。而不是参考 A_CLASS.a 直接参考 self :

    def Foo(self):
      print self.a
      print self.b
    

    自己 如果不存在该名称的实例属性,将查找类属性。如果要百分之百确定它来自类而不是实例,可以将其定义为:

    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\U类 并将其绑定到名称 B\U类 ,您不能通过名称来引用它 A\U类 用于查找(因为程序中没有具有该绑定的部分)。

        2
  •  2
  •   Silvio Mayolo    6 年前

    问题是你使用了这个名字 A_CLASS 字面上在 Foo . 始终可以使用 self.__class__ .

    def Foo(self):
      print self.__class__.a
      print self.b