是的,它必须处理这一事实ins通常是生成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,以及其他具有不同类型的优点。
所以,如果是 enumerate
和 reversed
原因很简单,因为它能提供更高的性能和更容易维护。
其他优点包括:
- 你可以添加方法到type( e .g 。
chain.from_iterable
) 。 还可能是做了3 个函数,但是你必须先定义它们,然后手工设置这些属性,这看起来也没那么干净。 - 我们可以
isinstance
在iterables 。 这可能影响一些optimizations( e .g如果知道 isinstance(iterable, itertools.repeat)
,则你也许能够优化代码,因为你知道哪些值就认输了。
编辑: 问清楚我这样说是指:
在C,我如果不包含。 生成器,则应创建一个代码对象的一个新实例,它包含实际的字节码。
在看 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
s 是当执行一个python解释器时字节码internally( e .g 。 a PyCodeObject
可以表示的字节码函数),即: yes,以创建一个PyGen_Type
从字节码 C 则必须手动创建的实例,这并不是很容易的创建 PyCodeObject
s,因为 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)
请注意其中包含参数如 firstlineno
, filename
这当然意味着要想通过python源文件,而不是从其他C代码获得。 C 中显然可以创建公用文件夹,可我一点也不相信,它将需要的字符比编写一个简单的新类型。