gpt4 book ai didi

python - 为什么一些 python 内置 "functions"实际上是类型?

转载 作者:太空狗 更新时间:2023-10-29 17:47:22 25 4
gpt4 key购买 nike

__builtin__ 模块中的许多迭代器“函数”实际上是作为类型实现的,尽管文档将它们称为“函数”。以 enumerate 为例。文档说它等同于:

def enumerate(sequence, start=0):
n = start
for elem in sequence:
yield n, elem
n += 1

当然,这与我实现的完全一样。但是,我使用之前的定义运行了以下测试,并得到了这个:

>>> x = enumerate(range(10))
>>> x
<generator object enumerate at 0x01ED9F08>

这是我所期望的。但是,当使用 __builtin__ 版本时,我得到了这个:

>>> x = enumerate(range(10))
>>> x
<enumerate object at 0x01EE9EE0>

据此我推断它被定义为

class enumerate:
def __init__(self, sequence, start=0):
# ....

def __iter__(self):
# ...

文档显示的不是标准 形式。现在我可以理解这是如何工作的,以及它是如何等同于标准形式的,我想知道的是这样做的原因是什么。这样效率更高吗?它是否与用 C 实现的这些功能有关(我不知道它们是否有关,但我怀疑是这样)?

我使用的是 Python 2.7.2,以防差异很重要。

提前致谢。

最佳答案

是的,这与内置函数通常在 C 中实现这一事实有关。C 代码通常会引入新类型而不是普通函数,如 enumerate 的情况。用 C 编写它们可以更好地控制它们,并且通常可以提高一些性能,由于没有真正的缺点,这是一个自然的选择。

考虑到编写等价于:

def enumerate(sequence, start=0):
n = start
for elem in sequence:
yield n, elem
n += 1

在 C 中,即 生成器的新实例,您应该创建一个包含实际字节码的代码对象。这并非不可能,但并不比编写一个简单地实现 __iter____next__ 调用 Python C-API 的新类型更容易,再加上具有不同的其他优点类型。

因此,在 enumeratereversed 的情况下,这仅仅是因为它提供了更好的性能,并且更易于维护。

其他优势包括:

  • 您可以向类型添加方法(例如 chain.from_iterable)。这甚至可以通过函数来​​完成,但您必须先定义它们,然后手动设置属性,这看起来不太干净。
  • 您可以在可迭代对象上使用 isinstance。这可能允许进行一些优化(例如,如果您知道 isinstance(iterable, itertools.repeat),那么您可以优化代码,因为您知道将产生哪些值。

编辑:只是为了澄清我的意思:

in C, i.e. a new instance of a generator, you should create a code object that contains the actual bytecode.

查看 Objects/genobject.c 创建 PyGen_Type 实例的唯一函数是 PyGen_New 其签名是:

PyObject *
PyGen_New(PyFrameObject *f)

现在,查看 Objects/frameobject.c 我们可以看到,要创建一个 PyFrameObject,您必须调用 PyFrame_New,它有这个签名:

PyFrameObject *
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
PyObject *locals)

如您所见,它需要一个 PyCodeObject 实例。 PyCodeObject 是 python 解释器在内部表示字节码的方式(例如 PyCodeObject 可以表示函数的字节码),所以:是的,创建一个 来自 C 的 PyGen_Type 实例,您必须手动创建字节码,并且创建 PyCodeObject 并不容易,因为 PyCode_New 具有此签名:

PyCodeObject *
PyCode_New(int argcount, int kwonlyargcount,
int nlocals, int stacksize, int flags,
PyObject *code, PyObject *consts, PyObject *names,
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
PyObject *filename, PyObject *name, int firstlineno,
PyObject *lnotab)

请注意它如何包含诸如 firSTLinenofilename 之类的参数,这些参数显然是由 python 源代码获取的,而不是来自其他 C 代码的。显然您可以用 C 语言创建它,但我完全不确定它是否会比编写一个简单的新类型需要更少的字符。

关于python - 为什么一些 python 内置 "functions"实际上是类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14861572/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com