Rocky Raccoon
Rocky Raccoon

Reputation: 51

AttributeError: 'str' object has no attribute 'items' Error when Looping

def printdash():
    print('-' * 10)


# creates a mapping of state to abbreviation
states = {
'Oregon': 'OR',
'Florida': 'FL',
'California': 'CA',
'New York': 'NY',
'Michigan': 'MI'
}

# creates a basic set of states with some cities in them

cities = {
'CA': 'Sacramento',
'MI': 'Lansing', 
'FL': 'Tallahasee'}

# add some more cities to the list
cities['NY'] = 'Albany'
cities['OR'] = 'Eugene'

# Print out some cities
printdash()
print('New York State has: ', cities['NY'])
print('Oregon has: ', cities['OR'])

# print some states
printdash()
print 'Michigan\'s abbreviation is: ' , states['Michigan']
print 'Florida\'s abbreviation is: ', states['Florida']

# do it by using the state then cities dict. Nested dicts!
printdash()
print 'Michigan has: ', cities[states['Michigan']]
print 'Florifa has: ', cities[states['Florida']] 

# print every states abbreviation
printdash()
for states, abbrev in states.items():
    print '%s is abbreviated as %s' % (states, abbrev)
# end

# print every city in each state
printdash()
for abbrev, cities in cities.items():
    print '%s has the city %s' % (abbrev, cities)
# end

# doing both at the same time
printdash()
for state, abbrev in states.items():
    print '%s state is abbreviated %s and has city %s' % (state, abbrev,  cities[abbrev])

Each time i run it it will get to Line 54 (the last for loop) and then raise the Attribute Error flag. For the life of me i cant figure out what I am doing wrong as the other two loops, set up in mostly the same fashion work without issue.

Looking up other solutions on this site, i found the examples used to be a bit more complex than i could understand and the solutions seemed to be a little more specific than this very general case.

Shanks!

Upvotes: 1

Views: 8763

Answers (3)

AlexV
AlexV

Reputation: 590

The line

for states, abbrev in states.items():
    print('%s is abbreviated as %s' % (states, abbrev))

causes the trouble.

As the scope of loop variables in python is not limited to the loop (you can say, they 'leak' into your program), after this line states will be a string.

You can debug this by running

print(states)
for states, abbrev in states.items():
    print('%s is abbreviated as %s' % (states, abbrev))
print(states)

which will print

----------
{'California': 'CA', 'Michigan': 'MI', 'New York': 'NY', 'Florida': 'FL', 'Oregon': 'OR'}
California is abbreviated as CA
Michigan is abbreviated as MI
New York is abbreviated as NY
Florida is abbreviated as FL
Oregon is abbreviated as OR
Oregon

Additionally, you should check your use of print. Please stick with one version of the print statement, either print 'foo' OR print('foo'). The second usage (as function) is the only one that will work in Python 3.X.

Upvotes: 1

vasanthi vuppuluri
vasanthi vuppuluri

Reputation: 31

Both 'cities' and 'states' are being overwritten in the first and second for loops. Using different variable names should fix it.

Upvotes: 1

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160657

When you assign states as the target in your first loop you re-assign the name for states to the first item of the states.items() tuple.

Here's a simplified version of what you are doing:

>>> i = "hello"
>>> for i in range(2): print i
... 
0
1
>>> i
1

As you see, i is an int after the loop and not an str, the value it refers to has changed.


As a solution simply rename the states in your loop to something else, like state or tmp_states. So:

for state, abbrev in states.items():
    print '%s is abbreviated as %s' % (state, abbrev)

Additionally do the same for the other loops where the same pattern exists, like for abbrev, cities in cities.items(): -> for abbrev, city in cities.items().

Upvotes: 2

Related Questions