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



许多Python内置的"函数"实际上是类,尽管它们也有一个简单的函数实现。即使是非常简单的,比如itertools.repeat。这样做的动机是什么?在我看来,这似乎是过度工程。

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

def repeat(x):
    while True: yield x

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

我也理解类是可调用的函数,以及如何使用类来模拟类似函数的行为。但我不明白为什么它通过标准库被如此广泛地使用。

作为itertools的类实现具有一些生成器函数所不具备的优点。例如:

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

对于非生成器工具,原因通常类似。类可以被赋予状态和自定义行为,而函数却不能。它们可以从(如果需要的话,但是如果C层类是"逻辑上"的函数,则可以禁止子类化)。

对于动态实例创建也很有用;如果你有一个未知类的实例,但有一个已知的原型(比如,序列构造函数接受一个可迭代对象,或chain或其他),你想把其他类型转换成那个类,你可以做type(unknown)(constructorarg);如果它是一个生成器,type(unknown)是无用的,你不能用它来制造更多的自己,因为你不能自省找出它的来源(不合理的方式)。

除此之外,即使你从不使用编程逻辑的特性,你宁愿在交互式解释器中看到什么,或者在type(myiter), <class 'generator'>的打印调试中看到没有提示来源,或者<class 'itertools.repeat'>告诉你确切的东西和它来自哪里?

函数和类都是可调用对象,因此它们可以在高阶函数中互换使用,例如

$ python2
... 
>>> map(dict, [["ab"], ["cd"], ["ef"]])
[{'a': 'b'}, {'c': 'd'}, {'e': 'f'}]
>>> map(lambda x: dict(x), [["ab"], ["cd"], ["ef"]])
[{'a': 'b'}, {'c': 'd'}, {'e': 'f'}]
也就是说,类还可以定义方法,您可以稍后在返回的对象上调用这些方法。例如,dict类为字典等定义了.get()方法。

itertools.repeat(和大多数迭代器)的情况下,使用一个适当的类实现iterator协议从实现/维护POV有一些好处——比如你可以更好地控制迭代,你可以专门化类等。我也怀疑有一些优化可以在c级对适当的迭代器进行,而不适用于生成器。

还要记住,类和函数也是对象——def语句主要是用于创建function实例并使用编译代码、本地名称空间、单元格、闭包和诸如此类的东西填充它的语法糖(这在某种程度上涉及到任务FWIW,我曾经只是出于好奇而做过一次,这是一个主要的PITA), class语句也是用于创建新的type实例的语法糖(手动执行它实际上是非常微不足道的)。从这个POV来看,yield是一个类似的语法糖,它把你的函数变成一个返回通用generator内置类型实例的工厂——它使你的函数像一个类,没有编写一个完整的类的麻烦,但也没有精细的控制和可能的优化,你可以通过编写一个完整的类。

在更一般的层面上,有时将你的"函数"写成一个自定义的可调用类型反而会提供类似的收益——精细的控制,可能的优化,有时只是更好的可读性(想想两步装饰器,自定义描述符等)。

最后wrt/内置类型(int, str等)IIRC(如果我错了,请有人纠正我)它们最初是作为工厂函数的函数(在新型类革命之前,内置类型和用户定义类型是不同类型的对象)。现在将它们作为普通类当然是有意义的,但是为了兼容性,它们必须保持all_lower命名方案。

相关内容

最新更新