0

When I was learning the Python Crash Course, one question that is not answered in the book is to use an Instance as Attributes.

Let me show a quick example:

class Car():
    def __init__(self, make, model):
        self.make = make
        self.model = model
        self.tank = Tank()

    def get_car_info(self):
        long_name = self.make + ' ' + self.model
        print('The car is', long_name)

class Tank():
    def __init__(self, tank_size=20):
        self.tank_size = tank_size
    def tank_info(self):
        print('The tank size is', self.tank_size, 'gallons')

my_car = Car('Audi', 'S4')
my_car.get_car_info()
my_car.tank.tank_info()

>>>
The car is Audi S4
The tank size is 20 gallons

Apparently, I created two classes named Car and Tank, I want to use the Tank class instance as an attribute for the Car. The codes will work out, no problem here.

But what I noticed is that the code that I invoke the Tank method:

my_car.tank.tank_info()

If I understand correctly, the first 'tank' should mean the class 'Tank'. So why should I lowercase it? I tried to upper case, the code won't work.

3
  • my_car is an instance of Car. my_car has an attribute named tank which was assigned an instance of Tank when it was created. my_car.tank. ... is accessing my_car's tank attribute`. Commented Sep 24, 2017 at 2:20
  • 1
    self.tank = Tank() assigned an instance; self.tank = Tank would have assigned the class itself. Commented Sep 24, 2017 at 2:21
  • @wwii thank you so much!! this is crystal clear now!! Commented Sep 24, 2017 at 2:29

2 Answers 2

1

if..

class Car():
    def __init__(self, make, model):
        self.make = make
        self.model = model
        self.tank = Tank()

was

class Car():
    def __init__(self, make, model):
        self.make = make
        self.model = model
        self.tnk = Tank()

Then you would call my_car.tnk.tank_info()

If it was

class Car():
    def __init__(self, make, model):
        self.make = make
        self.model = model
        self.t = Tank()

Then you would call my_car.t.tank_info().

So to answer your question you are not referring to the class Tank but you are referring to a member of class Car which is of type class Tank

Sign up to request clarification or add additional context in comments.

1 Comment

I see, so the tank is really not referring to the Tank class, but the 'tank' under 'self.tank'. Thanks a lot!!
1

Because an attribute will have the name that you give it. One could give it the same name as the class-name, but that is generally avoided, and by convention, attributes are snake_case in Python. But there is nothing stopping you from doing something like:

>>> class Foo:
...     pass
...
>>> class Bar:
...     def __init__(self):
...         self.Foo = Foo()
...         self.foo = Foo()
...         self.FOO = Foo()
...
>>> b = Bar()
>>> b.foo
<__main__.Foo object at 0x1021c2710>
>>> b.Foo
<__main__.Foo object at 0x1021c26d8>
>>> b.FOO
<__main__.Foo object at 0x1021c2748>

This is a contrived example of a Bar object that has three attributes, all three of which are different instances of Foo, and I used a different style to name each of them.

I think that one fundamental thing you must grok is that you've always been using instances as attributes. Everything is an instance. str objects are instances of class str, int objects are instances of class int, list objects are instances of class list, just like Foo objects are instances of class Foo. Everything is an object in Python.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.