我有两个班级:
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
。
所以最终的问题是:如果我在方法体中(不是类方法),我如何获得定义方法的类的名称?
答案 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