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.
精彩评论