Beginner Python: AttributeError: 'list' object has no attribute

306,063

Solution 1

Consider:

class Bike(object):
    def __init__(self, name, weight, cost):
        self.name = name
        self.weight = weight
        self.cost = cost

bikes = {
    # Bike designed for children"
    "Trike": Bike("Trike", 20, 100),      # <--
    # Bike designed for everyone"
    "Kruzer": Bike("Kruzer", 50, 165),    # <--
    }

# Markup of 20% on all sales
margin = .2
# Revenue minus cost after sale
for bike in bikes.values():
    profit = bike.cost * margin
    print(profit)

Output:

33.0
20.0

The difference is that in your bikes dictionary, you're initializing the values as lists [...]. Instead, it looks like the rest of your code wants Bike instances. So create Bike instances: Bike(...).

As for your error

AttributeError: 'list' object has no attribute 'cost'

this will occur when you try to call .cost on a list object. Pretty straightforward, but we can figure out what happened by looking at where you call .cost -- in this line:

profit = bike.cost * margin

This indicates that at least one bike (that is, a member of bikes.values() is a list). If you look at where you defined bikes you can see that the values were, in fact, lists. So this error makes sense.

But since your class has a cost attribute, it looked like you were trying to use Bike instances as values, so I made that little change:

[...] -> Bike(...)

and you're all set.

Solution 2

They are lists because you type them as lists in the dictionary:

bikes = {
    # Bike designed for children"
    "Trike": ["Trike", 20, 100],
    # Bike designed for everyone"
    "Kruzer": ["Kruzer", 50, 165]
    }

You should use the bike-class instead:

bikes = {
    # Bike designed for children"
    "Trike": Bike("Trike", 20, 100),
    # Bike designed for everyone"
    "Kruzer": Bike("Kruzer", 50, 165)
    }

This will allow you to get the cost of the bikes with bike.cost as you were trying to.

for bike in bikes.values():
    profit = bike.cost * margin
    print(bike.name + " : " + str(profit))

This will now print:

Kruzer : 33.0
Trike : 20.0

Solution 3

You need to pass the values of the dict into the Bike constructor before using like that. Or, see the namedtuple -- seems more in line with what you're trying to do.

Share:
306,063
Charles Watson
Author by

Charles Watson

A JavaScript expert with a focus in Angular, React, Node, and other MEAN/MERN stack technologies. I currently work for NaviStone LLC, a disruptive advertising and analytics company. As a senior engineer and head of Agile practices, I lead a full-stack Agile team developing pure React front-ends with Nodejs and .NET backends. My engineering passion derives from learning, leading and teaching. When not on my computer building things, you can usually either find me hiking with my dog, at my local skydiving dropzone, or, in the colder months skiing the day away.

Updated on November 25, 2020

Comments

  • Charles Watson
    Charles Watson over 3 years

    The error says:

    AttributeError: 'list' object has no attribute 'cost' 
    

    I am trying to get a simple profit calculation to work using the following class to handle a dictionary of bicycles:

    class Bike(object):
        def __init__(self, name, weight, cost):
            self.name = name
            self.weight = weight
            self.cost = cost
    
    bikes = {
        # Bike designed for children"
        "Trike": ["Trike", 20, 100],
        # Bike designed for everyone"
        "Kruzer": ["Kruzer", 50, 165]
        }
    

    When I try to calculate profit with my for statement, I get the attribute error.

    # Markup of 20% on all sales
    margin = .2
    # Revenue minus cost after sale
    for bike in bikes.values():
        profit = bike.cost * margin
    

    First, I don't know why it is referring to a list, and everything seems to be defined, no?

  • Kevin
    Kevin about 9 years
    This would be a better answer if you explained the difference between your code and OP's.
  • jedwards
    jedwards about 9 years
    @Kevin edited it after I posted it -- actually going to revise it again to explain the initial error.