为了账号安全,请及时绑定邮箱和手机立即绑定

如何获取绑定方法的定义类?

如何获取绑定方法的定义类?

qq_花开花谢_0 2021-09-23 09:02:36
我做了一个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 2class 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__. 理想情况下,我想正确检查身份if cls is repr_defined_in_cls。我见过的所有 SO 问题都只针对获取类的字符串名称,而不是用于比较的类。有没有更好的方法来获取定义该方法的(原始)类?
查看完整描述

2 回答

?
12345678_0001

TA贡献1802条经验 获得超5个赞

检查类__dict__以获取"__repr__"密钥:


if "__repr__" in vars(cls):

    # repr overriden in class. Don't mess with it

else:

    cls.__repr__ = AutoRepr.__repr__


查看完整回答
反对 回复 2021-09-23
?
慕容3067478

TA贡献1773条经验 获得超3个赞

当然,走过去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

完全取决于您需要的语义。我想你明白要点了。


查看完整回答
反对 回复 2021-09-23
  • 2 回答
  • 0 关注
  • 157 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号