派生类时python abc subclasshook没有效果
Posted
技术标签:
【中文标题】派生类时python abc subclasshook没有效果【英文标题】:python abc subclasshook has no effect when class is derived 【发布时间】:2017-07-22 13:45:43 【问题描述】:当类派生自具有__sub***ook__
实现的类时,无法从issubclass 返回False
。我修改了以下代码:
python subclasscheck & subclasshook
我只在两个类定义中添加了 '(Sized)':
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
?还是我做错了什么?
【问题讨论】:
当然我发现代码片段(在 abc 中)以:ok = cls.__subclasshook__(subclass)
如果我遗漏了一些东西,请原谅,但你能不能用return False
替换return NotImplemented
吗?您在 PEP8 中有什么要坚持的吗?
@leaf:谢谢,太明显了。但是为什么所有的例子都只返回True
或NotImplemented
。
我相信这是因为 [Python]() 标准在实现“魔术方法”时所要求的。
【参考方案1】:
问题是你return NotImplemented
当__subclasshook__
没有提前退出。正如documentation中所述:
如果它返回 NotImplemented,则使用通常的机制继续检查子类。
所以它使用普通的子类检查并发现你确实继承自Sized
所以返回True
。
有两种解决方案:
return False
而不是return NotImplemented
。但是,您真的希望/需要issubclass
为直接子类返回False
?
如果您从 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
【讨论】:
Ad 1. 是的,假设这是类似于其他语言中的编译(或反射)的机制。如果怀疑该类是正确的子类,则代码不应运行甚至编译(不在 python 中)。广告 2. 我明白了,是来自链接的代码。【参考方案2】:我认为实现这一点的好方法:
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 中)。
【讨论】:
请不要只是转储代码,请解释为什么这样可以解决问题。否则您可能还想考虑accept我的回答,其中还包含相关信息+解释。以上是关于派生类时python abc subclasshook没有效果的主要内容,如果未能解决你的问题,请参考以下文章