我做了一个 AutoRepr
类和类 decorator
...
class AutoRepr:
def __repr__(self):
def _fix(thing):
if isinstance(thing, str):
return f'"{thing}"'
if isinstance(thing, Iterable):
s = str(thing)
if len(s) > 30:
return type(thing)
else:
return s
return thing
props = []
try:
for attr in self.__slots__:
if attr.startswith('_'):
continue
try:
attr_val = getattr(self, attr)
if attr_val:
props.append(f'{attr}={_fix(attr_val)}')
except AttributeError:
pass
except AttributeError:
props = [f'{k}={_fix(v)}'
for k, v in self.__dict__.items()
if not k.startswith('_')]
return f'{type(self).__name__}({", ".join(props)})'
def auto_repr(override_all=False):
def decorator(cls):
repr_defined_in = cls.__repr__.__qualname__.split('.')[0]
if not override_all and repr_defined_in == cls.__name__:
# repr overriden in class. Don't mess with it
return cls
cls.__repr__ = AutoRepr.__repr__
return cls
return decorator
# Example 1
@auto_repr()
class MyClass:
def __init__(self):
self.strength = None
self.weakness = 'cake'
# Example 2
class Another(AutoRepr):
__slots__ = ('num', 'my_list')
def __init__(self):
self.num = 12
self.my_list = [1, 2, 3]
f = MyClass()
print(f)
b = Another()
print(b)
# MyClass(strength=None, weakness="cake")
# Another(num=12, my_list=[1, 2, 3])
在装饰器中,我需要检查包装类 __repr__
是否在类中被覆盖或是否属于父类。如果 __repr__
已被类覆盖,那么我不希望 auto_repr 做任何事情,但是,如果没有,那么显然希望 auto-repr 做它的事情。通过 __qualname__
比较 repr 方法绑定(bind)类的字符串名称,我设法拼凑出一个解决方案,但感觉既便宜又笨重。理想情况下,我想正确检查身份if cls is repr_defined_in_cls
。
我见过的所有 SO 问题都只解决获取类的字符串名称,而不是用于比较的类。有没有更好的方法来获取定义方法的(原始)类?
最佳答案
当然,走 mro
并确保您点击的第一个 __repr__
不是来自 object
:
In [18]: class A:
...: pass
...:
...: class B(A):
...: def __repr__(self): return "a repr"
...:
...: class C(B):
...: pass
...:
...:
In [19]: def is_non_default_repr(klass):
...: for superclass in klass.mro():
...: if '__repr__' in vars(superclass):
...: return superclass is not object
...: return False # should we ever get here? maybe raise error?
...:
...:
In [20]: is_non_default_repr(A)
Out[20]: False
In [21]: is_non_default_repr(B)
Out[21]: True
In [22]: is_non_default_repr(C)
Out[22]: True
我相信,如果元类使用 __slots__
,这将失败,但那将是一个非常反常的现象。
编辑:
重新阅读您的要求,您可以执行以下操作:
In [23]: def which_method(klass, methodname):
...: for superclass in klass.mro():
...: if methodname in vars(superclass):
...: return superclass
...: raise ValueError(f"{methodname} not a member")
...:
...:
In [24]: which_method(C, '__repr__') is not object
Out[24]: True
In [25]: which_method(C, '__repr__')
Out[25]: __main__.B
In [26]: which_method(C, '__repr__') is C
Out[26]: False
In [27]: which_method(B, '__repr__') is B
Out[27]: True
具体取决于您需要的语义。我想您明白了要点。
关于python - 如何获取绑定(bind)方法的定义类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53889849/