2011-11-09 1 views
5
old = [1, 2, 3] 

(もしあれば)次の2行の違いは何ですか?python list copy:古い[:]とリスト(古い)の違いはありますか?

new = old[:] 
new = list(old) 

更新は、私はすでにubershmekelの答えを受け入れていたが、後に、私は興味深い事実を学んだ:[:]は小さなリスト(10個の要素)が、list()のために高速であるより速く、より大きなリスト(100000の要素)のために。

~$ python -S -mtimeit -s "a = list(range(10))" "a[:]" 
1000000 loops, best of 3: 0.198 usec per loop 
~$ python -S -mtimeit -s "a = list(range(10))" "list(a)" 
1000000 loops, best of 3: 0.453 usec per loop 
~$ python -S -mtimeit -s "a = list(range(100000))" "a[:]" 
1000 loops, best of 3: 675 usec per loop 
~$ python -S -mtimeit -s "a = list(range(100000))" "list(a)" 
1000 loops, best of 3: 664 usec per loop 

答えて

5

はい、小さな違いがあります。最近、/r/pythonにディスカッションがありました。this blog postは可読性の違いを説明した後、[:]はジェネレータとは動作せず、元のタイプと同じタイプを保持しています。

技術的には、同じオブジェクトを指し示す新しいリストです。あなたが好きな方を選んでください([:]は少し速いですが)。個人的に私はlist(old)が読みやすくなっているというブログ投稿に同意します。

は、Python 3.2で、特定の違いについてのコメントに答えるために:

>>> import dis 
>>> def colon(x): 
...  return x[:] 
... 
>>> def new_list(x): 
...  return list(x) 
... 
>>> 
>>> dis.dis(colon) 
    2   0 LOAD_FAST    0 (x) 
       3 LOAD_CONST    0 (None) 
       6 LOAD_CONST    0 (None) 
       9 BUILD_SLICE    2 
      12 BINARY_SUBSCR 
      13 RETURN_VALUE 
>>> dis.dis(new_list) 
    2   0 LOAD_GLOBAL    0 (list) 
       3 LOAD_FAST    0 (x) 
       6 CALL_FUNCTION   1 
       9 RETURN_VALUE 
>>> 

はなぜlist(old)があると思い遅いスライスメカニズムは、リスト上に「LOAD_GLOBAL」と「CALL_FUNCTION」を必要としないので、コンストラクタでは、全体の操作はC言語で処理されます。

+0

なぜ[:]は少し速いのですか? –

+0

@MattFenwick 'list(x)'は、グローバル変数 'list'を検索し、1つの引数を持つ関数を呼び出す必要があります。 'x [:]'はこれらのどちらもしないのでオーバーヘッドが少なくなります。それが長いリストであれば、その差はごくわずかです(そして短いリストでさえもおそらく重要ではありません)。 – Duncan

+1

可読性は主観的であり、バックグラウンドによって異なります。そのブログや別の関連記事では、私は[:]表記を「暗黙の」表記と呼びました。よく... – joaquin

0

古いが配列の場合、どちらも同じです。しかし、古いものがある種のイテレータならば、リスト()の構文だけが動作します。そのため、より一般的なので、2番目の構文がおそらく好ましいでしょう。

5

oldがリストでない場合、古い[:]は古いものと同じ種類のコンテナ(古いタプルまたは文字列)のすべての古い要素になります。リスト(古いもの)は同じ要素。

I.e.もし古いものが文字列 'foo'なら、古い[:]は文字列 'foo'になり、list(old)はリスト['f'、 'o'、 'o']になります。

+0

ありがとう、これは関連していますが、 'old'がリストである場合について具体的に質問しました(私の最初の行' old = [1、2、3] ') – bpgergo

+0

@bpgergo何歳のように見えるかの例。とにかく、害はありません、私は願っています。 :-) –

0

new = old[:]は、スライス表記を使用してリストoldのコピーを作成し、newに格納します。

new = list(old)oldをタイプlistにキャストします。それは既にリストであり、newに割り当てられています。

私はこれらの両方が同じ結果をもたらすと信じています。つまり、newにはoldのコピーが含まれています。

0

この2つの機能的な違いはまだ誰も言及していません。 [:]は意味がありません:

>>> i = iter([1,2,3]) 
>>> i[:] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'listiterator' object is not subscriptable 
>>> list(i) 
[1, 2, 3] 
+0

ありがとう、これは関連していますが、古いものがリストである場合について具体的に尋ねました(私の最初の行を見てください、古い= [1、2、3]) – bpgergo

0

あなたが与える例では、違いはありません。同じ要素を持つブランドの新しいlistオブジェクト内の結果、両方のリスト(a_generator)はa_generatorの一方で、動作します。一般

  • new = old[:]

    はスライスのみをサポートするオブジェクトで動作します、とnewは古い

  • new = list(old)と同じタイプの任意の反復可能で動作します、とnewlist
になりますでしょう
関連する問題