Python中导入numpy后sum()函数的结果与之前不同。

6

我看到了Jake VanderPlas提出的这个问题,但我不确定在导入numpy模块后为什么结果会有所不同,我的理解是否完全正确。

>>print(sum(range(5),-1)
>> 9
>> from numpy import *
>> print(sum(range(5),-1))
>> 10

在第一种情况下,sum函数似乎计算可迭代对象的总和,然后从总和中减去第二个参数的值。
在第二种情况下,导入numpy库后,该函数的行为似乎已经修改,因为第二个参数用于指定应执行总和的轴。
练习编号(24) 来源-http://www.labri.fr/perso/nrougier/teaching/numpy.100/index.html

1
你的问题是什么? - Michael Lorton
14
这就是为什么你永远不要使用 import *。 - YXD
1
这个练习的重点在于np.sum与内置的sum是不同的——所以如果你不小心,*可能会很危险。 - hpaulj
1
@Malvolio 我想要澄清这个行为。我从这两个函数及其参数的文档中推断出我的原因,但想知道我是否正确。 - aamir23
2个回答

11

"当第二个参数用于指定应执行求和的轴时,该函数的行为似乎已经改变。"

您基本上回答了自己的问题!

技术上说,不能说该函数的行为已经被修改。使用from numpy import *将结果“shadowing”了内置的sum函数,并使用numpy sum函数,因此当您使用名称sum时,Python会找到numpy版本而不是builtin版本(有关详细信息,请参见@godaygo的答案)。这些是具有不同参数的不同函数。通常情况下,出于这个原因,使用from somelib import *是一个坏主意。相反,使用import numpy as np,然后在需要numpy函数时使用np.sum,在需要Python builtin函数时使用普通的sum


是的,这正是我从这两个函数的文档中推断出来的,我认为这是某种函数重载,但想要确认一下。非常感谢您详细的解释。 - aamir23

10

只是为了给 @Warren Weckesser 的答案增添一些我的五分钱。真正的情况是,from numpy import * 并没有覆盖内置函数 sum,它只是遮蔽了 __builtins__.sum,因为 from ... import * 语句将导入模块中定义的除下划线开头的所有名称绑定到当前的 global 命名空间中。根据 Python 的名称解析规则 (非官方的 LEGB 规则),Python 会先在你的 global 命名空间中查找,然后才会在 __builtins__ 命名空间中查找。所以如果 Python 找到所需的名称,在这种情况下是 sum,它就会返回绑定的对象,而不会再往下查找。

编辑: 为了向你展示发生了什么:

 In[1]: print(sum, ' from ', sum.__module__)    # here you see the standard `sum` function
Out[1]: <built-in function sum>  from  builtins

 In[2]: from numpy import *                     # from here it is shadowed
        print(sum, ' from ', sum.__module__)
Out[2]: <function sum at 0x00000229B30E2730>  from  numpy.core.fromnumeric

 In[3]: del sum                                 # here you restore things back
        print(sum, ' from ', sum.__module__)
Out[3]: <built-in function sum>  from  builtins

第一条注意事项del 不会删除对象,这是垃圾收集器的任务,它只是“取消引用”名称绑定并从当前命名空间中删除名称。

第二个注意事项:内置函数sum的签名为sum(iterable[, start])

从左到右对iterable 的项目及 start 进行求和,并返回总和。start 默认为 0 。可迭代的项目通常是数字,而不允许将字符串用作起始值。

在您的情况下,对于内置的sumprint(sum(range(5),-1) 将以 -1 开始进行求和。 因此,在技术上,您的短语通过对可迭代项求和然后从总和减去第二个参数的值不正确。 对于数字,真正要紧的是是否某个值开始或者稍后添加/相加/相减。 但是对于列表来说,则有所不同(仅是愚蠢的示例,仅用于说明这个想法):

 In[1]: sum([[1], [2], [3]], [4])
Out[1]: [4, 1, 2, 3]               # not [1, 2, 3, 4]
希望这能澄清您的想法 :)

Hope this will clarify your thoughts :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接