Создать список словарей Python
Я хочу получить все iframe
с веб-страницы.
Код:
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)
:
{'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'}
результат pprint(content)
:
[{'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)
.
Ответы
Ответ 1
Вы не создаете отдельный словарь для каждого 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)
Существуют и другие способы достижения этой цели, такие как итерация по списку атрибутов или использование переходов по спискам или словарю, но трудно улучшить ясность приведенного выше кода.
Ответ 2
Вы неправильно поняли объект 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(dlist)
не совпадает с print(d)
?
В следующем коде показана причина:
>>> 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
Ответ 3
Если вам нужна одна строка:
list_of_dict = [{} for i in range(list_len)]
Ответ 4
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')
...