V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
James369
V2EX  ›  Python

isinstance 函数似乎施加魔法,可以自动判断?

  •  
  •   James369 · 2021-05-14 15:42:02 +08:00 · 1575 次点击
    这是一个创建于 1280 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我在构造一个自定义迭代器 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 ???
    
    4 条回复    2021-05-14 16:53:22 +08:00
    fengjianxinghun
        1
    fengjianxinghun  
       2021-05-14 15:55:00 +08:00   ❤️ 2
    假如你看起来像鸭子,叫起来像鸭子,走起路来像鸭子,那你就是鸭子。


    https://docs.python.org/3/library/stdtypes.html#typeiter
    knightdf
        2
    knightdf  
       2021-05-14 15:57:53 +08:00   ❤️ 1
    建议你看看 collections.abc.Iterable 的文档
    geelaw
        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() 仍然识别为子类。
    abersheeran
        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
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3385 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:47 · PVG 12:47 · LAX 20:47 · JFK 23:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.