python abc subclass 钩子在派生 class 时无效
python abc subclasshook has no effect when class is derived
当 class 派生自 class 并具有 __subclashook__
实现时,无法从 issubclass return False
。我修改了代码:
我只在两个 class 定义中添加了“(大小)”:
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
这种情况下有什么办法可以return False
吗?或者我做错了什么?
问题是当 __subclasshook__
没有提前退出时,您 return NotImplemented
。正如 documentation 中所述:
If it returns NotImplemented, the subclass check is continued with the usual mechanism.
所以它使用正常的子类检查,发现你做的,实际上是继承自Sized
所以returns True
.
有两种解决方法:
return False
而不是 return NotImplemented
。然而,你真的want/needissubclass
到returnFalse
for直接sub类吗?
如果您从 object
继承 类 A
和 B
它会按预期工作:
class A(object):
pass
class B(object):
def __len__(self):
return 0
print(issubclass(A, Sized)) # False
print(issubclass(B, Sized)) # True
我认为实现这个的好方法:
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
是类似于其他语言的编译(或反射)的机制时,我们应该 return False。如果怀疑 class 是正确的 subbclass 那么代码不应该 运行 甚至编译(不在 python 中)。
当 class 派生自 class 并具有 __subclashook__
实现时,无法从 issubclass return False
。我修改了代码:
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
这种情况下有什么办法可以return False
吗?或者我做错了什么?
问题是当 __subclasshook__
没有提前退出时,您 return NotImplemented
。正如 documentation 中所述:
If it returns NotImplemented, the subclass check is continued with the usual mechanism.
所以它使用正常的子类检查,发现你做的,实际上是继承自Sized
所以returns True
.
有两种解决方法:
return False
而不是return NotImplemented
。然而,你真的want/needissubclass
到returnFalse
for直接sub类吗?如果您从
object
继承 类A
和B
它会按预期工作:class A(object): pass class B(object): def __len__(self): return 0 print(issubclass(A, Sized)) # False print(issubclass(B, Sized)) # True
我认为实现这个的好方法:
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
是类似于其他语言的编译(或反射)的机制时,我们应该 return False。如果怀疑 class 是正确的 subbclass 那么代码不应该 运行 甚至编译(不在 python 中)。