每个函数调用都重新初始化python函数中的变量吗?

时间:2011-01-25 09:29:35

标签: python function-calls timeit

假设我有两个功能

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

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

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

3 个答案:

答案 0 :(得分:2)

如果不做一些非常复杂的分析,Python就无法做你的建议。赋值语句只是一个赋值语句,如果我在解释器中键入x=3两次我希望x在我键入之后就是3而不管我在x之间做了什么......这真的没有什么不同< / p>

说明 - 该功能很容易

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

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

这个过程忽略了biglist是一个不同的变量每次调用的事实 - 你可以让这个func同时在2个线程上执行而且它们是不相关的

答案 1 :(得分:0)

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

- 西

答案 2 :(得分: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”,但是如果你必须拥有共享的全局数据,并且这个列表只是从头开始构建,那么习惯使用它并不是一个糟糕的范例。一次(然后复制)可能会带来一些性能改进。