如何从方法体中获取定义类?

时间:2016-09-14 10:10:08

标签: python class python-3.x methods

我有两个班级:

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

class B(A):
    pass

现在,我需要用以下代码替换<get the defining class>

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

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

A
A

我尝试了self.__class__.__name__,但显然会为最后一次通话产生B,因为self实际上属于班级B

所以最终的问题是:如果我在方法体中(不是类方法),我如何获得定义方法的类的名称?

2 个答案:

答案 0 :(得分:2)

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

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__的每个类的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])

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

答案 1 :(得分:-1)

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

如果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