python中类型的“可迭代”、“迭代器”示例吗?

use*_*834 1 python

这是一个关于python(动态)类型系统如何工作的问题。我在网上读过一些文章,说要将一个类定义为“可迭代”,我们需要__iter__为它定义一个函数。我们实际上不必明确声明该类“是可迭代的”。我会根据使用其他语言的经验猜测我必须编写类似的东西

class Foo extends Iterable:
   def __iter__(self):
      return self
Run Code Online (Sandbox Code Playgroud)

当我测试类型Foo及其实例之一时,我得到:

print(type(Foo))
print(type(Foo()))
print(isinstance(Foo(), collections.abc.Iterable))
Run Code Online (Sandbox Code Playgroud)

输出:

<class 'type'>
<class '__main__.Foo'>
True
Run Code Online (Sandbox Code Playgroud)

我的问题是:在 python 的(动态)类型系统中,像“Iterable”这样的概念的状态是什么?我应该认为它与类型有任何关系吗?

Gre*_*Guy 5

Atype是 python 调用通过class语句定义的任何对象。使用 Java 作为参考点,type类似于java.lang.Class- 代表类的类。

“可迭代”更类似于接口而不是——而类/类型同时定义了内部状态和某些方法,而接口只定义了这些方法。Python 不像其他语言那样将其形式化,但该原理用于 Python 的大多数“隐藏”方法(两侧有两个下划线的方法)。如果为类定义了特定的隐藏方法(例如,__iter__()),则该类被认为是可迭代的*。

在你的例子中,你isinstance()用来证明你的观点。python 文档实际上在 上有一个页面collections.abc,其中详细介绍了它们的行为:

该模块提供抽象基类,可用于测试类是否提供特定接口;例如,它是否是可散列的或是否是映射。

(加粗以强调)。

它甚至特别提到了迭代器:

class collections.abc.Iterable

ABC 表示提供__iter__()方法的类。

检查isinstance(obj, Iterable)会检测注册为 Iterable 或具有__iter__()方法的类,但不会检测使用该__getitem__()方法进行迭代的类。确定对象是否可迭代的唯一可靠方法是调用iter(obj).

Python 允许 ABC 类通过定义元类方法基本上劫持内置isinstance()调用,这就是为什么尽管没有继承自.__instancecheck__()isinstance(Foo(), Iterable)FooIterable


*虽然这些函数的输入和输出没有像 Java 这样的静态类型语言那样严格定义,但调用它们的内置方法有非常具体的期望,实际上会产生同样的结果。例如,我曾经遇到一个问题,试图覆盖__len__()一个对象以返回一个浮点数而不是一个整数,因为len()当我试图在该对象上使用它时,内置函数抛出了一个错误。