1

假设我有两个功能

def myfunction1(number):

    biglist = [1,2,3,4,5,6,7,8,9]

    print number*biglist


biglist = [1,2,3,4,5,6,7,8,9]

def myfunction2(number, biglist):

    print number*biglist

我用 ipython 的魔法 %timeit 计时:

In [5]: %timeit myfunction2(number, biglist)
1000000 loops, best of 3: 607 ns per loop

In [6]: %timeit myfunction1(number)
1000000 loops, best of 3: 841 ns per loop

这是否意味着biglist每次调用 myfunction1 时都会重新声明该变量?我会猜到,在第一次函数调用之后,Python 会以某种方式将biglist变量与函数一起存储,这样它就不必在每次调用函数时重新初始化列表。

我不知道 Python 的内部工作原理,所以我只是猜测。有人可以解释实际发生的事情吗?

4

3 回答 3

2

如果不进行一些相当复杂的分析,Python 将无法执行您的建议。x=3如果我在解释器中键入两次,则赋值语句只是一个赋值语句

举例说明-该功能很容易

def myfunction1(number):
    biglist = [1,2,3,4,5,6,7,8,9]
    biglist = number*biglist
    print biglist

在这种情况下,您要重新分配 biglist。

这当然忽略了 biglist 每次调用都是一个不同的变量这一事实——你可以让这个函数同时在 2 个线程上执行,它们是不相关的

于 2011-01-25T09:35:51.293 回答
0

是的.. 它在 myfunction1 的范围内,而在 myfunction2 的范围内,它在全局范围内,直到程序结束才会结束。一旦 myfunction1 完成,任何与之关联的变量都将被标记为不可访问。并且每次调用都只会在其范围内创建一个新的 vars。

——赛

于 2011-01-25T09:33:25.420 回答
0

Python 必须在 myfunction1() 的每个条目上创建一个新列表,并将其分配给“biglist”。

在 myfunction2() 中,您传递了对全局范围的“biglist”的引用,因此无需进行复制。

两者之间还有其他细微的差异。传入该引用会使全局数据容易受到(可能不需要的)干扰:

>>> biglist = [ 1,2,3,4,5,6,7,8,9 ]
>>> def myfunction3(mylist):
...     mylist[2] = 99
...
>>> biglist
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> myfunction3(biglist)
>>> biglist
[1, 2, 99, 4, 5, 6, 7, 8, 9]

...而在函数范围内声明它意味着它每次都重新创建。因此,例如:

>>> def myfunction4():
...     mylist = [ 1,2,3,4,5 ]
...     print mylist
...     mylist[2] = 99
...
>>> myfunction4()
[1, 2, 3, 4, 5]
>>> myfunction4()
[1, 2, 3, 4, 5]

每次调用该函数时,您都会得到一份新鲜、干净、纯粹的列表副本供您使用。

那么如何才能两全其美呢?试试这个:

>>> def myfunction5():
...     mylist = biglist+[] # Make a private copy
...     mylist[4] = 99
...
>>> biglist
[1, 2, 99, 4, 5, 6, 7, 8, 9]
>>> myfunction5()
>>> biglist
[1, 2, 99, 4, 5, 6, 7, 8, 9]

您可以看到全局范围列表没有改变。基于此方法的新功能将是:

def myfunction1a(number):
    mylist = biglist+[] # Copy-safe version
    print number*mylist

使用您的基准时间进行比较如何?我知道在这种情况下,您实际上并没有在函数中修改“biglist”,但如果您必须共享全局数据,并且列表只是从头开始构建,那么习惯使用它并不是一个糟糕的范例一次(然后复制)可能会带来一些性能改进。

于 2011-01-25T13:04:05.373 回答