Home > OS >  why list items in output are repetitive?
why list items in output are repetitive?

Time:11-08

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. code:

output:

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:

fixed code:

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)
  • Related