这是一个关于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”这样的概念的状态是什么?我应该认为它与类型有任何关系吗?
Atype是 python 调用通过class语句定义的任何对象。使用 Java 作为参考点,type类似于java.lang.Class- 代表类的类。
“可迭代”更类似于接口而不是类——而类/类型同时定义了内部状态和某些方法,而接口只定义了这些方法。Python 不像其他语言那样将其形式化,但该原理用于 Python 的大多数“隐藏”方法(两侧有两个下划线的方法)。如果为类定义了特定的隐藏方法(例如,__iter__()),则该类被认为是可迭代的*。
在你的例子中,你isinstance()用来证明你的观点。python 文档实际上在 上有一个页面collections.abc,其中详细介绍了它们的行为:
该模块提供抽象基类,可用于测试类是否提供特定接口;例如,它是否是可散列的或是否是映射。
(加粗以强调)。
它甚至特别提到了迭代器:
class collections.abc.IterableABC 表示提供
__iter__()方法的类。检查
isinstance(obj, Iterable)会检测注册为 Iterable 或具有__iter__()方法的类,但不会检测使用该__getitem__()方法进行迭代的类。确定对象是否可迭代的唯一可靠方法是调用iter(obj).
Python 允许 ABC 类通过定义元类方法基本上劫持内置isinstance()调用,这就是为什么尽管没有继承自.__instancecheck__()isinstance(Foo(), Iterable)FooIterable
*虽然这些函数的输入和输出没有像 Java 这样的静态类型语言那样严格定义,但调用它们的内置方法有非常具体的期望,实际上会产生同样的结果。例如,我曾经遇到一个问题,试图覆盖__len__()一个对象以返回一个浮点数而不是一个整数,因为len()当我试图在该对象上使用它时,内置函数抛出了一个错误。
| 归档时间: |
|
| 查看次数: |
44 次 |
| 最近记录: |