2017-03-02 31 views
0

当从派生类__subclashook__实现时,无法从issubclass返回False。我修改从代码: python subclasscheck & subclasshook 我只加“(大小)”这两个类定义:python abc subclasshook在派生类时不起作用

from abc import ABCMeta 

class Sized(metaclass=ABCMeta): 
    @classmethod 
    def __subclasshook__(cls, C): 
     if cls is Sized: 
      if any("__len__" in B.__dict__ for B in C.__mro__): 
       return True 
     return NotImplemented 

class A(Sized): 
    pass 

class B(Sized): 
    def __len__(self): 
     return 0 

print(issubclass(A, Sized)) # True - should be False 
print(issubclass(B, Sized)) # True 

有没有办法在这种情况下返回False?或者,也许我做错了什么?

+0

,当然我发现了开头的代码片段(在ABC): 'OK = CLS .__ subclasshook __(子类)' – PiotrB

+1

原谅我,如果我失去了一些东西,但你能不能只替换'而归NotImplemented' '返回False'?你试图坚持的PEP8中有什么? –

+0

@叶夫:谢谢,这太明显了。但是为什么所有的例子只返回'True'或'NotImplemented'。 – PiotrB

回答

3

问题是,你return NotImplemented__subclasshook__不提前退出。并且如documentation中所述:

如果它返回NotImplemented,则子类检查将继续使用通常的机制。

所以它使用正常的子类检查,发现你做什么,其实,继承Sized所以返回True

解决办法有两个:

  1. return False而不是return NotImplemented。然而,你真的想/需要issubclass返回False直接子类

  2. 如果从object上课AB继承它按预期工作:

    class A(object): 
        pass 
    
    class B(object): 
        def __len__(self): 
         return 0 
    
    print(issubclass(A, Sized)) # False 
    print(issubclass(B, Sized)) # True 
    
+0

Ad 1.是的,当假设它是类似于其他语言的编译(或反射)机制。如果有人怀疑这个类是正确的子类,那么代码不应该运行,甚至编译(不是在python中)。 广告2.我了解它,它是链接代码。 – PiotrB

1

我认为实现这个好办法:

from abc import ABCMeta 

class Sized(metaclass=ABCMeta): 
    @classmethod 
    def __subclasshook__(cls, C): 
     if cls is Sized: 
      if any("__len__" in B.__dict__ for B in C.__mro__): 
       return True 
      else: 
       return False 
     return NotImplemented 


class A(Sized): 
    pass 


class B(Sized): 
    def __len__(self): 
     return 0 


print(issubclass(A, Sized)) # False 
print(issubclass(B, Sized)) # True 

我认为,当我们假设abc与其他语言中编译(或反射)类似,我们应该返回False。如果有人怀疑这个类是正确的子类,那么代码不应该运行,甚至编译(不是在python中)。

+0

请不要只是转储代码,解释为什么这解决了这个问题。否则,您可能还想考虑[接受](http://stackoverflow.com/help/accepted-answer)我的答案,其中也包含相关信息+解释。 – MSeifert