1

这是一个后续问题(与我提出的这个问题有关)但它足够复杂,我认为最好开始一个新问题。

以前,我发现无论出于何种原因,我都有:

isinstance([], UserString) == True

但这显然是不对的。经过一堆挖掘,我认为我的其他代码导致了这个问题,但我不知道这怎么可能。

这是可以重现上述问题结果的最少代码:

if __name__ == "__main__":
    def func_decorator(func):
        def wrapper(*args, **kwargs):
            res = func(*args, **kwargs)
            return res
        return wrapper

    def class_decorator(cls):
        # set of callable function names already been decorated/inspected
        handled_funcs = {'__new__', '__init__', '__del__', '__getattr__', '__getattribute__', '__class__'}
        for key in cls.__dict__:
            # Only callable functions are decorated
            value = getattr(cls, key)
            if not callable(value):
                continue
            handled_funcs.add(key)
            setattr(cls, key, func_decorator(value))
        # Handle the remaining base classes (skip Mixin)
        for base in cls.__mro__[2:]:
            for key in base.__dict__:
                value = getattr(base, key)
                if not callable(value) or key in handled_funcs:
                    continue
                handled_funcs.add(key)
                setattr(cls, key, func_decorator(value))
        return cls

    class Mixin():
        def __init_subclass__(cls, **kwargs):
            super().__init_subclass__(**kwargs)
            class_decorator(cls)

    class MyUserString(Mixin, UserString):
        def __init__(self, seq, *, synthesized=False):
            super().__init__(synthesized, seq)

    print(isinstance([], UserString)) # this will print True

我删除了大部分其他代码,这些代码实际上做了我需要的有用的事情。基本上,我MyUserString使用__init_subclass__in 进行装饰,Mixin以便 inMyUserString及其基类(我跳过Mixin)中的所有方法都由func_decorator. 在装饰过程中,我按照MRO,跳过已经根据处理过的方法handled_funcs(即handled_funcs有所有不应该被装饰的方法,要么是我不希望它们被装饰,要么是因为它们已经被装饰,例如,__new__我在一开始就添加)。

现在,我发现有趣的是,如果我__subclasshook__在集合中添加,我得到了正确的结果,即 isinstance([], UserString) == False. 但为什么?func_decorator简单地返回与原始函数相同的值,更重要的是,UserString甚至没有被修饰class_decorator(我认为,因为setattr总是为 设置属性cls,即MyUserString,但也许我错了)?

我知道UserString继承自ABCABC以某种方式定义__subclasshook__isinstance...但是我不能将两个和两个放在一起!有人可以解释发生了什么吗?

4

0 回答 0