基本上,表达式0.4 * a始终比a * 0.4快得多,而且令人惊讶的是.a为整数.我也不知道为什么.

我推测这是一个LOAD_CONST LOAD_FAST字节码对比LOAD_FAST LOAD_CONST"更专业"的情况,我会对这个解释完全满意,只是这个怪癖似乎只适用于相乘变量类型不同的乘法.(顺便说一句,我再也找不到我在GitHub上找到的这份《字节码指令对受欢迎程度排名》的链接了,有人有链接吗?)

无论如何,以下是微观基准:

$ python3.10 -m pyperf timeit -s"a = 9" "a * 0.4"
Mean +- std dev: 34.2 ns +- 0.2 ns
$ python3.10 -m pyperf timeit -s"a = 9" "0.4 * a"
Mean +- std dev: 30.8 ns +- 0.1 ns
$ python3.10 -m pyperf timeit -s"a = 0.4" "a * 9"
Mean +- std dev: 30.3 ns +- 0.3 ns
$ python3.10 -m pyperf timeit -s"a = 0.4" "9 * a"
Mean +- std dev: 33.6 ns +- 0.3 ns

正如你所看到的--在彩车排在第一位(第二和第三)的比赛中--它更快.
所以我的问题是,这种行为是从哪里来的?我90%确定这是CPython的实现细节,但我不太熟悉低级指令来确定这一点.

推荐答案

它是CPythonBINARY_MULTIPLY操作码的实现.它不知道编译时的类型是什么,所以所有事情都必须在运行时弄清楚.不管ab可能是什么,BINARY_MULTIPLY最终都是INKING a.__mul__(b).

a是整型时,int.__mul__(a, b)不知道该做什么,除非b也是整型.它返回Py_RETURN_NOTIMPLEMENTED(内部C常量).这是在longobject.cCHECK_BINOP个宏中.翻译回答说:"好吧,a.__mul__不知道该怎么做,让我们试一试b.__rmul__吧."所有这些都不是免费的--这一切都需要时间.

float.__mul__(b, a)(与float.__rmul__相同)知道如何处理整型(首先将其转换为浮点型),因此成功了.

但当a开始是浮点型时,我们首先转到float.__mul__,这就结束了.没有时间go 弄清楚int类型不知道该做什么.

实际的代码比上面假装的要复杂得多,但这就是它的要点.

Python相关问答推荐

了解shuffle在NP.random.Generator.choice()中的作用

将numpy矩阵映射到字符串矩阵

Matlab中是否有Python的f-字符串等效物

如何检测背景有噪的图像中的正方形

Pytest两个具有无限循环和await命令的Deliverc函数

从dict的列中分钟

NP.round解算数据后NP.unique

将pandas Dataframe转换为3D numpy矩阵

如何更改分组条形图中条形图的 colored颜色 ?

try 将一行连接到Tensorflow中的矩阵

如果满足某些条件,则用另一个数据帧列中的值填充空数据帧或数组

Plotly Dash Creating Interactive Graph下拉列表

在matplotlib中使用不同大小的标记顶部添加批注

Gunicorn无法启动Flask应用,因为无法将应用解析为属性名或函数调用.'"'' "

我对这个简单的异步者的例子有什么错误的理解吗?

如何过滤组s最大和最小行使用`transform`'

一个telegram 机器人应该发送一个测验如何做?""

计算机找不到已安装的库'

如何在Gekko中处理跨矢量优化

如何训练每一个pandaprame行的线性回归并生成斜率