我在构造一个自定义迭代器 Test 类的时候发现一个奇特的现象,Test 类并没有继承自 Iterable,只是实现了__iter__和__next__函数。
然而创建的对象却可以判定是 Iterable 类型
class TestIterator():
def __init__(self, n):
...
def __iter__(self):
return self
def __next__(self):
...
t1 = Test()
isinstance(t1, Iterable) #返回 True !!!
然后我又创建了一组普通的类测试,发现又不行了:
class A:
def do1(self):
print('A do1')
class B(A):
def do2(self):
print('B do2')
class X:
def do1(self):
print('X do1')
a1 = A()
b1 = B()
x1 = X()
isinstance(b1, A) #True
isinstance(x1, A) #False ???
1
fengjianxinghun 2021-05-14 15:55:00 +08:00 2
|
2
knightdf 2021-05-14 15:57:53 +08:00 1
建议你看看 collections.abc.Iterable 的文档
|
3
geelaw 2021-05-14 16:33:19 +08:00 1
答案是因为 Iterable 是抽象基类 (abstract base class),但 A 不是。isinstance 对于抽象基类 (ABC) 有特殊的规则。
https://docs.python.org/3/library/functions.html#isinstance 当 object 是 classinfo 或它(直接、间接、虚拟)子类的实例时,返回 True 。 点击“虚拟”,可以看到 https://docs.python.org/3/glossary.html#term-abstract-base-class ABC 引入虚拟子类——虽然不继承,但 isinstance()、issubclass() 仍然识别为子类。 |
4
abersheeran 2021-05-14 16:53:22 +08:00 1
https://docs.python.org/3/reference/datamodel.html?highlight=instancecheck#class.__instancecheck__ 为你的 A 实现一个 __instancecheck__ 用以检查 do1 是否存在就行。
如果你觉得手工穷举检查麻烦,可以使用 https://docs.python.org/zh-cn/3/library/typing.html#typing.runtime_checkable |