bgoldber
bgoldber

Reputation: 51

How to retrieve an object from a Python Dictionary

I'm trying to retrieve an object that I've placed into a dictionary, but every time I try to retrieve it I receive an error:

  class CSVEntry:
    lat = []
    lon = []
    count = 0

  # Create dictionary for tracking inputs
  dict = defaultdict(list)

  # Lookup the zipcode (returns an integer value)
  zipcode = ConvertLatLonToZip(row[latCol], row[lonCol])

  # If the zipcode is already in the dictionary, update it with the new count
  if zipcode in dict:
    oldEntry = dict[zipcode]
    oldEntry.lat.append(row[latCol])
    oldEntry.lon.append(row[lonCol])
    oldEntry.count = dict[zipcode].count + 1

  # Otherwise, make a new entry
  else:
    entry = CSVEntry()
    entry.lat.append(row[latCol])
    entry.lon.append(row[lonCol])
    entry.count = 1

    # Hash on the zipcode
    dict[zipcode].append(entry)

It has no problem inserting entries into the dictionary, but as soon as it finds a duplicate, it fails with this error:

Traceback (most recent call last):
  File "ParseCSV.py", line 125, in <module>
    oldEntry.lat.append(row[latCol])
AttributeError: 'list' object has no attribute 'lat'

I apologize if this is a duplicate or a ridiculously simple question. I'm a beginner to Python and I searched for a long while before deciding to post.

EDIT: Added the definition of dict

Upvotes: 0

Views: 766

Answers (2)

Nolen Royalty
Nolen Royalty

Reputation: 18633

Right now oldEntry is a list. It looks like you want to change

if zipcode in dict:
    oldEntry = dict[zipcode]
    oldEntry.lat.append(row[latCol])
    oldEntry.lon.append(row[lonCol])
    oldEntry.count = dict[zipcode].count + 1

to

if zipcode in dict:
    oldEntry = dict[zipcode][0]
    oldEntry.lat.append(row[latCol])
    oldEntry.lon.append(row[lonCol])
    oldEntry.count += 1

That being said, it might make more sense to simply create a new CSVEntry object and append it to dict[zipcode] Alternatively, you could make dict a defaultdict containing CSVEntry objects, meaning that you wouldn't have to check whether zipcode was in dict. This would give you code like:

zip_dict = collections.defaultdict(CSVEntry)
zip_dict[zipcode].lat.append(row[latCol])
zip_dict[zipcode].lon.append(row[longCol])
zip_dict[zipcode].count += 1

This is likely the easiest way to solve your problem. On a sidenote, you want to avoid naming a variable dict as that overwrites the builtin dict type.

Upvotes: 2

3Doubloons
3Doubloons

Reputation: 2106

You made yourself a defaultdict containing lists. When you call dict[zipcode].append(entry), Python creates a new list and you insert your entry in that list. However, when you do oldEntry = dict[zipcode], you take that list and treat it as though it were a CSVEntry.

You should use a plain dict and insert your entries like so:

dict[zipcode] = entry

or append your item to the entry:

dict[zipcode].append(newEntry)

The point of a defaultdict is to abstract away the search for existing items. If you make a defaultdict of lists, you should not look for the entry in your dictionary, but simply append new ones when necessary; the defaultdict will take care of giving you a new list to play with when you ask for a non-existing key.

Upvotes: 0

Related Questions