在Python中如何实现**?
我想知道在哪里可以找到关于Python中**这个运算符是怎么实现的资料。有人能给我指个方向吗?
4 个回答
我觉得caseysrandomthoughts是在问关于函数定义时的星号(*)用法。
你可以在这个Python文档页面找到答案:http://docs.python.org/tutorial/controlflow.html#more-on-defining-functions
当函数的最后一个参数是**name这种形式时,它会接收一个字典,这个字典包含了所有的关键字参数,除了那些已经对应到正式参数的。
我在其他地方也看到过对这个内容的描述,但我记不起来了。
有两种不同的实现方式,一种是针对整数(在3.0版本中是长整型)对象的,另一种是针对浮点数对象的。
浮点数的幂运算是通过一个叫做 float_pow(PyObject *v, PyObject *w, PyObject *z) 的函数来实现的,这个函数在Python源代码的Objects/floatobject.c文件中定义。这个函数会调用C标准库中的math.h里的pow()函数。
整数的幂运算有自己独特的实现方式,使用的是 int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z) 这个函数,它在Python源代码的Objects/intobject.c文件中定义(在3.0版本中是longobject.c)。
Python的语法定义(通过pgen生成解析器)中,有关'power'的部分可以查看这里:Grammar/Grammar
Python的抽象语法树(ast),有关'ast_for_power'的部分可以查看这里:Python/ast.c
Python的执行循环中,有关'BINARY_POWER'的部分可以查看这里:Python/ceval.c
这个部分会调用PyNumber_Power(在Objects/abstract.c中实现):
PyObject *
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
{
return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}
基本上,它会调用pow这个功能。对于长整型对象(在3.0版本中唯一的默认整数类型),这个功能在long_pow函数中实现,具体可以查看Objects/longobject.c,而对于整型对象(在2.x版本中),则是在int_pow函数中实现,具体可以查看Object/intobject.c
如果你深入了解long_pow函数,你会发现,在检查参数和做一些准备工作后,真正的指数运算的核心部分可以在这里看到:
if (Py_SIZE(b) <= FIVEARY_CUTOFF) {
/* Left-to-right binary exponentiation (HAC Algorithm 14.79) */
/* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf */
for (i = Py_SIZE(b) - 1; i >= 0; --i) {
digit bi = b->ob_digit[i];
for (j = 1 << (PyLong_SHIFT-1); j != 0; j >>= 1) {
MULT(z, z, z)
if (bi & j)
MULT(z, a, z)
}
}
}
else {
/* Left-to-right 5-ary exponentiation (HAC Algorithm 14.82) */
Py_INCREF(z); /* still holds 1L */
table[0] = z;
for (i = 1; i < 32; ++i)
MULT(table[i-1], a, table[i])
for (i = Py_SIZE(b) - 1; i >= 0; --i) {
const digit bi = b->ob_digit[i];
for (j = PyLong_SHIFT - 5; j >= 0; j -= 5) {
const int index = (bi >> j) & 0x1f;
for (k = 0; k < 5; ++k)
MULT(z, z, z)
if (index)
MULT(z, table[index], z)
}
}
}
这个部分使用了在应用密码学手册的第14.6章中讨论的算法,这些算法描述了高效的任意精度算术的指数运算方法。