2011-01-25 16 views
1

は私がipythonのマジック%のはtimeitでそれらを時間を計る二つの機能Python関数の変数は、関数呼び出しごとに再初期化されますか?

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 

があるとします。

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の内部動作を知らないので、私はちょうど推測しています。誰かが実際に何が起こるか説明できますか?

+0

'timeit'を使うのは、一度だけ実行したように時間を実行することです! – SilentGhost

+0

私は分かりません。この例では、私のtimeitの使い方が間違っていますか? – Viktiglemma

答えて

2

非常に複雑な分析を行うことなく、Pythonはあなたの提案をすることはできません。代入文は、私がx=3をインタプリタで2回入力すると代入文になります。xの間にxを入力した直後にxが3になると期待しています...これは実際には違う...

to説明する - その機能は簡単に可能性があります。

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

この場合、ビッグリストを再割り当てする必要があります。

このofcourseのはBIGLISTが別の変数すべてのコールであるという事実を無視する - あなたは、これは同時に2つのスレッド上で実行FUNCかもしれないと、彼らは無関係

0

はい..これはmyfunction1の範囲内にあり、myfunction2ではプログラムが終了するまで終了しないグローバルスコープにあります。 myfunction1が完了すると、それに関連付けられている血管は到達不能とマークされます。そして、すべての呼び出しは、そのスコープ内にのみ新しいvarsを作成します。

- サイ

+0

f1でグローバルではありません – tobyodavies

+1

グローバルはグローバルを意味しません。あなたは私がそれを参照したコードを与えました。関数の範囲外です。 myfunction1にwrtです。それを必要としない外側の範囲に分けてください。 –

+1

本当に届かないとマークされていません。退屈な古いリファレンスカウントGCは、このクリーンアップを処理します(少なくともcpythonでは) –

0

Pythonは上の新しいリストを作成しなければならないだろうmyfunction1()への各エントリは、 'biglist'に割り当てます。

myfunction2()では、グローバルスコープの「biglist」への参照を渡しているため、コピーは行われません。

この2つの間には、他にも微妙な違いがあります。グローバルデータは(おそらく不要)干渉に開いている参照して葉を渡す:

>>> 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"を変更しているわけではありませんが、グローバルデータを共有しなければならない場合は、使い慣れたパラダイムではなく、リストは最初から作成されるということです一度(そしてコピーされると)パフォーマンスが向上するかもしれません。

+0

myfunction1a(number)関数は実際にmyfunction1と同じスピードを持ちますが、それは別のものより安全です。 – Viktiglemma

関連する問題