为什么许多Python内置/标准库函数实际上是类

use*_*134 6 python class standard-library

许多Python内置的"函数"实际上是类,尽管它们也有简单的函数实现.甚至非常简单,例如itertools.repeat.这是什么动机?这对我来说似乎过度工程化了.

编辑:我不是在询问其目的itertools.repeat或任何其他特定功能.它只是一个非常简单的函数的示例,具有非常简单的可能的实现:

def repeat(x):
    while True: yield x
Run Code Online (Sandbox Code Playgroud)

itertools.repeat实际上它不是一个函数,它是作为一个类实现的.我的问题是:为什么?这似乎是不必要的开销.

另外我理解类是可调用函数,以及如何使用类模拟类函数行为.但我不明白为什么它通过标准库如此广泛使用.

Sha*_*ger 5

作为类实现itertools具有生成器功能所不具备的一些优点.例如:

  1. CPython在C层实现这些内置函数,在C层,生成器"函数"最好实现为实现__next__将状态保存为实例属性的类; yield基于生成器的Python层是精确的,实际上,它们只是generator类的一个实例(所以它们实际上仍然是类实例,就像Python中的其他所有实例一样)
  2. 生成器不是可拾取的或可复制的,并且没有"故事"使它们支持任何一种行为(内部状态太复杂和不透明而不能概括它); 一个类可以定义__reduce__/ __copy__/ __deepcopy__(如果它是一个Python级别的类,它可能甚至不需要这样做;它会自动工作)并使实例可选择/可复制(所以如果你已经从range迭代器生成了5个元素,你可以复制或pickle/unpickle它,并在迭代中获得相同距离的迭代器)

对于非发电机工具,原因通常是相似的.可以为类提供状态和定制的行为,而函数则不能.它们可以从中继承(如果需要,但C层类可以禁止子类化,如果它们是"逻辑"函数).

它对于动态实例创建也很有用; 如果你有一个未知类的实例但是一个已知的原型(比如,带有可迭代的序列构造函数,chain或者其他什么),并且你想将其他类型转换为该类,你可以这样做type(unknown)(constructorarg); 如果它是一个发电机,type(unknown)是无用的,你不能用它来制造更多的东西,因为你无法想象它是从哪里来的(不是以合理的方式).

而除此之外,即使你从来没有使用的功能进行编程逻辑,你会更愿意看到在交互式解释或做的打印调试type(myiter),<class 'generator'>即没有给出提示为原点,或者<class 'itertools.repeat'>告诉你,你有什么和它是从哪里来从?