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.
2 Answers 2
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
1 Comment
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.
my_caris an instance ofCar.my_carhas an attribute namedtankwhich was assigned an instance ofTankwhen it was created.my_car.tank. ...is accessingmy_car'stankattribute`.self.tank = Tank()assigned an instance;self.tank = Tankwould have assigned the class itself.