Python weakref.proxy 对象被认为是可迭代的?

Python weakref.proxy object considered iterable?

我遇到了以下情况(使用 Python 3.8.3):

from collections.abc import Iterable
from weakref import proxy

class Dummy:
   pass

isinstance(d := Dummy, Iterable)
# False (as expected)

isinstance(p := proxy(d), Iterable)
# True (why?!)

for _ in p:
    # raises TypeError
    pass

代理对象如何通过可迭代测试?

它提供 __iter__ 以防基础类型提供它。 __iter__ 必须 在类型上实现才能工作,而不是在实例上实现,因此它不能有条件地定义 __iter__ 而不分裂成许多不同的 class es,不只是一个 proxy class.

不幸的是,Iterable 测试只是检查 class 是否定义了 __iter__,而不是它是否有效,proxy 不知道它是否 really 无需调用包装的 class 的 __iter__ 即可工作。如果您想检查可迭代性,只需对其进行迭代,如果失败则捕获 TypeError 。如果你不能立即迭代它,而它受制于 time-of-check/time-of-use 竞争条件,你可以编写自己的简单测试器来测试它是否可以 实际上 被迭代:

def is_iterable(maybeiter):
    try:
        iter(maybeiter)
    except TypeError:
        return False
    else:
        return True