2017-03-02 87 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