开发者

Are variables in python functions reinitialized with each function call?

Assume I have two functions

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

I time them with ipython's magic %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

Does this mean that the biglist variable is re-declared every time I call myfunction1? I would have guessed that after the first function-call Python would somehow store the biglist variable with the function, so that it would not have to re-initialize the list every time the function is called.

I don't know the inner wo开发者_StackOverflow社区rkings of Python so I'm just guessing. Can someone explain what actually happens?


Python can't do what you suggest without doing some quite complicated analysis. the assignment statement is just an assignment statement if i type x=3 twice in the interpreter i expect x to be 3 just after i type it regardless of what i have done to x in between... this is really no different

to illustrate - that function could easily be

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

in which case you want to reassign biglist.

This ofcourse ignores the fact that biglist is a different variable every call - you could have this func executing on 2 threads at the same time and they would be unrelated


Yes.. It is inside the scope of myfunction1 and in myfunction2 it is in global scope which will not end till program ends. Once myfunction1 is completed any vars associated with it will be marked unreachable. And every invocation will create a new vars only in its scope.

--Sai


Python has to create a new list on each entry to myfunction1(), and assign it to 'biglist'.

In myfunction2(), you are passing a reference to the global-scoped 'biglist', so there's no copying to be done.

There are other, subtle differences between the two. Passing in that reference leaves the global data open to (possibly unwanted) interference:

>>> 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]

...whereas, declaring it in function scope means it's created anew every time. So, for instance:

>>> 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]

Each time the function's called, you've got a fresh, clean, unadulterated copy of the list to play with.

So how do you get the best of both worlds? Try this:

>>> 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]

You can see that global-scope list is unchanged. Your new function, based upon this method, would be:

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

How does that compare using your benchmark timings? I know that in this case you're not actually modifying "biglist" in your function, but it's not a bad paradigm to get used to using, if you must have shared global data, and the fact that the list is only constructed from scratch once (and then copied) might give some performance improvements.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜