i have a list named events and loop over it via for loop through each iteration i update the values of dict and then append it to the list. so i desire that list items dont be repetitive and be different.
i tested that if i put the dict definition into the for loop, it will be fixed. but my question is why it doesn't work when dict definition is out of the for loop?
import requests
from bs4 import BeautifulSoup
url = 'https://www.python.org/events/python-events/'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
events = soup.find('ul', {'class': 'list-recent-events'}).findAll('li')
events_list = []
events_dict = dict()
for event in events:
events_dict['name'] = event.find('h3').find("a").text
events_dict['location'] = event.find('span', {'class': 'event-location'}).text
events_dict['time'] = event.find('time').text
events_list.append(events_dict)
for items in events_list:
print(items)
CodePudding user response:
It is because you overwrite the content of dict
with every iteration if it is outside the loop but in list
it is only a reference and not a new dict
. If you move it into the loop it will work, cause it is focused to each iteartion and become a separat/individual dict
:
for event in events:
events_dict = dict()
events_dict['name'] = event.find('h3').find("a").text
events_dict['location'] = event.find('span', {'class': 'event-location'}).text
events_dict['time'] = event.find('time').text
events_list.append(events_dict)
Example
However you could also simplify your code a bit:
import requests
from bs4 import BeautifulSoup
url = 'https://www.python.org/events/python-events/'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
events = soup.find('ul', {'class': 'list-recent-events'}).find_all('li')
events_list = []
for event in events:
events_list.append({
'name': event.h3.text,
'location': event.find('span', {'class': 'event-location'}).text,
'time': event.find('time').text,
})
for items in events_list:
print(items)
CodePudding user response:
the answer is related to the topic of cloning objects (shallow copy and deep copy): Assignment statements in python do not create copies of objects, they only bind names to an object. for immutable objects, that usually don't make a difference. but for working with mutable objects (like the list used here) the assignments statement only creates shallow copies
so the code fixed after using deepcopy
method:
import requests
from bs4 import BeautifulSoup
import copy
url = 'https://www.python.org/events/python-events/'
req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
events = soup.find('ul', {'class': 'list-recent-events'}).findAll('li')
events_list = []
events_dict = dict()
for event in events:
events_dict['name'] = event.find('h3').find("a").text
events_dict['location'] = event.find('span', {'class': 'event-location'}).text
events_dict['time'] = event.find('time').text
events_list.append(copy.deepcopy(events_dict))
for items in events_list:
print(items)