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

我做了一个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__. 理想情况下,我想正确检查身份if cls is repr_defined_in_cls。


我见过的所有 SO 问题都只针对获取类的字符串名称,而不是用于比较的类。有没有更好的方法来获取定义该方法的(原始)类?


qq_花开花谢_0
浏览 158回答 2
2回答

12345678_0001

检查类__dict__以获取"__repr__"密钥:if "__repr__" in vars(cls):    # repr overriden in class. Don't mess with itelse:    cls.__repr__ = AutoRepr.__repr__

慕容3067478

当然,走过去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]: FalseIn [21]: is_non_default_repr(B)Out[21]: TrueIn [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 objectOut[24]: TrueIn [25]: which_method(C, '__repr__')Out[25]: __main__.BIn [26]: which_method(C, '__repr__') is COut[26]: FalseIn [27]: which_method(B, '__repr__') is BOut[27]: True完全取决于您需要的语义。我想你明白要点了。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python