I want to know why the following codes work?
#!/usr/bin/env python3
import sys
class Car():
def __init__(self):
pass
if __name__ == '__main__':
c = Car()
c.speed = 3
c.time = 5
print(c.speed, c.time)
I accidentally found that I don't have to init attributes in init. I learn from every tutor I have to put assignment in init like below.
#!/usr/bin/env python3
import sys
class Car():
def __init__(self):
self.speed = 3
self.time = 5
if __name__ == '__main__':
c = Car()
print(c.speed, c.time)
If there are some official documents can explain this would be better.
It's class attributes vs instance attributes vs dynamic attributes. When you do:
class Car():
def __init__(self):
pass
c = Car()
c.speed = 3
c.time = 5
speed
and time
are dynamic attributes (not sure if this is an official term). If the usage of the class is such that these attributes are set before calling any other methods of Car
, then those methods can use self.speed
. Otherwise, you get an error:
>>> d = Car()
>>> d.speed
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute 'speed'
>>>
This happens because for c
, speed and time are attributes on that instance of Car
. Their existence or value doesn't propagate across other instances of Car. So when I create d
and then try to lookup d.speed
, the attribute doesn't exist. As you've said in your own comment, "they spring into existence when they are first assigned to."
I accidentally found that I don't have to init attributes in init. I learn from every tutor I have to put assignment in init like below.
Your tutors were very wrong or you misunderstood what they meant. In the example you gave, every Car gets the same initial speed
and time
. Typically, an __init__
would look like this:
class Car():
def __init__(self, speed, time): # notice that speed and time are
# passed as arguments to init
self.speed = speed
self.time = time
You can then initialise a Car
with: c = Car(3, 5)
. Or put default values in init if it's optional.
Edit: example adapted from the docs:
class Dog:
kind = 'canine' # class variable shared by all instances
def __init__(self, name):
self.name = name # instance variable unique to each instance
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
>>> e.name # unique to e
'Buddy'
>>> d.age = 3 # dynamic attribute/variable, unique to d
>>> d.age
3
>>> e.age # e doesn't have it at all
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Dog' object has no attribute 'age'