2012-07-15 23 views
20

私はすべてのiframeをウェブページから入手したいと思います。辞書のPythonのリストを作成

コード:

site = "http://" + url 
f = urllib2.urlopen(site) 
web_content = f.read() 

soup = BeautifulSoup(web_content) 
info = {} 
content = [] 
for iframe in soup.find_all('iframe'): 
    info['src'] = iframe.get('src') 
    info['height'] = iframe.get('height') 
    info['width'] = iframe.get('width') 
    content.append(info) 
    print(info)  

pprint(content) 

print(info)の結果:pprint(content)

{'src': u'abc.com', 'width': u'0', 'height': u'0'} 
{'src': u'xyz.com', 'width': u'0', 'height': u'0'} 
{'src': u'http://www.detik.com', 'width': u'1000', 'height': u'600'} 

結果:

[{'height': u'600', 'src': u'http://www.detik.com', 'width': u'1000'}, 
{'height': u'600', 'src': u'http://www.detik.com', 'width': u'1000'}, 
{'height': u'600', 'src': u'http://www.detik.com', 'width': u'1000'}] 

なぜ正しくないコンテンツの価値はありますか?私がprint(info)のときの値と同じであると考えられます。

答えて

43

あなたがちょうど何度も同じ辞書を変更保つ、各iframe対応の別々の辞書を作成していない、とあなたは追加追加し続けますリスト内のその辞書への参照。

content.append(info)のような操作を行うと、データのコピーが作成されないことに注意してください。単にデータへの参照を追加するだけです。

各iframeに新しい辞書を作成する必要があります。

for iframe in soup.find_all('iframe'): 
    info = {} 
    ... 

空の辞書を最初に作成する必要はありません。ただ、一度にすべてを作成します。

for iframe in soup.find_all('iframe'): 
    info = { 
     "src": iframe.get('src'), 
     "height": iframe.get('height'), 
     "width": iframe.get('width'), 
    } 
    content.append(info) 

は、このような属性のリストを反復処理、またはリストや辞書内包表記を使用するなど、これを達成する他の方法がありますが、それは上記のコードの明瞭さを改善するのは難しいです。

+0

おかげで、これは、Pythonを使用して私の最初のコードです。また、素早く応答してくれてありがとう – l1th1um

2

infoは、辞書へのポインタです。あなたのリストに同じポインタを追加し続けます。contactループに

挿入info = {}、それは問題を解決する必要があります:

... 
content = [] 
for iframe in soup.find_all('iframe'): 
    info = {} 
    info['src'] = iframe.get('src') 
    info['height'] = iframe.get('height') 
    info['width'] = iframe.get('width') 
... 
25

あなたはPython listオブジェクトを誤解しています。これはC pointer-arrayに似ています。それはあなたがそれに追加するオブジェクトを実際に "コピー"しません。代わりに、そのオブジェクトへのポインタを格納するだけです。

は、次のコードを試してみてください。

>>> d={} 
>>> dlist=[] 
>>> for i in xrange(0,3): 
    d['data']=i 
    dlist.append(d) 
    print(d) 

{'data': 0} 
{'data': 1} 
{'data': 2} 
>>> print(dlist) 
[{'data': 2}, {'data': 2}, {'data': 2}] 

をなぜprint(d)と同じprint(dlist)ではないでしょうか?

>>> for i in dlist: 
    print "the list item point to object:", id(i) 

the list item point to object: 47472232 
the list item point to object: 47472232 
the list item point to object: 47472232 

ですから、dlist内のすべての項目を見ることができますが、実際には同じdictオブジェクトを指している:

次のコードは、あなたの理由を示しています。

この質問に対する実際の答えは、d.copy()を使用して、対象アイテムの「コピー」を追加することです。

>>> dlist=[] 
>>> for i in xrange(0,3): 
    d['data']=i 
    dlist.append(d.copy()) 
    print(d) 

{'data': 0} 
{'data': 1} 
{'data': 2} 
>>> print dlist 
[{'data': 0}, {'data': 1}, {'data': 2}] 

あなたが実際に完全に別のオブジェクトを指すリスト項目を見ることができ、id()トリックを試してみてください。

>>> for i in dlist: 
    print "the list item points to object:", id(i) 

the list item points to object: 33861576 
the list item points to object: 47472520 
the list item points to object: 47458120 
+1

...すべての繰り返しで新しい辞書を作成するのではなく、ユーザーが '.copy()'メソッドを使うことを唱えていますか?私はこの特定のケースでは間違っていると思います。 –

+0

多くの場合、アイテムの一部だけを変更することができます。パフォーマンスと簡潔さの面では、私は '.copy()'を優先します。教育の側面では、 '.copy()'もより明確な概念を提供します。 – Wang

+2

'.copy()'は実際に何かをコピーしたいときだけ意味があると思います。一部のケースではアイテムの一部だけを変更したいと思うことに同意しますが、この特定の質問の場合、OPは、コピーと変更ではなく、iframeごとに新しい辞書を作成しようとしていたと思います。

3

あなたは1行たい場合:D:簡単な説明のための

list_of_dict = [{} for i in range(list_len)]