【问题标题】:How to get the defining class from a method body?如何从方法体中获取定义类?
【发布时间】:2016-09-14 10:10:08
【问题描述】:

我有两个班级:

class A:
    def foo(self):
        print(<get the defining class>)

class B(A):
    pass

现在,我需要用这样的代码替换 &lt;get the defining class&gt;

a = A()
b = B()
a.foo()
b.foo()

产生这个(即这是预期的行为):

A
A

我尝试了self.__class__.__name__,但这显然会为最后一次调用产生B,因为self 实际上属于B 类。

所以最终的问题是:如果我在一个方法体中(不是类方法),我怎样才能得到定义该方法的类的名称?

【问题讨论】:

  • 我很困惑。如果 A & A 是错误的,并且 A & B 不是您所期望的 - 您实际期望的是什么?
  • @JonClements 不,A & A 是正确的。我会改写这个问题,感谢您指出困惑。
  • 对...如果我们要做class C: def foo(self) # whatever - 那么class D(B, C) foo“定义”在哪里?

标签: python class python-3.x methods


【解决方案1】:

最简单的方法是使用函数限定名:

class A:
    def foo(self):
        print(self.foo.__qualname__[0])

class B(A):
    pass

限定名由定义的类和cls_name.func_name 形式的函数名组成。 __qualname__[0] 适合你,因为类名由单个字符组成;当然最好在点上拆分并返回第一个元素self.foo.__qualname__.split('.')[0]

对于两者,结果是:

>>> a = A()
>>> b = B()
>>> a.foo()
A
>>> b.foo()
A

一种更稳健的方法是爬上__mro__,并在每个类的__dict__s 中查找函数type(self).foo

def foo(self):
    c = [cls.__name__ for cls in type(self).__mro__ if getattr(type(self), 'foo', None) in cls.__dict__.values()]
    print(c[0])

这有点复杂,但产生相同的结果。

【讨论】:

    【解决方案2】:

    我假设您不想将此逻辑硬编码到每个函数中,因为您可以在示例代码中简单地这样做。

    如果print 语句始终是您想要此行为的方法的第一个语句,则一种可能的解决方案是使用装饰器。

    def print_defining_class(fn):
        calling_class = fn.__qualname__.split('.')[0]
        def decorated(*args, **kwargs):
            print(calling_class)
            return fn(*args, **kwargs)
        return decorated
    
    class A:
        @print_defining_class
        def method(self): pass
    
    class B(A): pass
    
    A().method() # A
    B().method() # A
    

    【讨论】:

      猜你喜欢
      • 2017-11-20
      • 2013-10-02
      • 1970-01-01
      • 2010-10-31
      • 2016-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多