2

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.

5
  • 2
    Did you read the official documentation on Classes in the Python Tutorial: docs.python.org/3/tutorial/classes.html Commented Aug 2, 2016 at 2:12
  • 2
    data attributes correspond to “instance variables” in Smalltalk, and to “data members” in C++. Data attributes need not be declared; like local variables, they spring into existence when they are first assigned to. Commented Aug 2, 2016 at 3:28
  • But I also want to know, in practice, what this feature is used for? It's not class variable, so it can not be shared. It looks like it's used to store some value, and if it's used for store some data, why not used instance variable instead? instance variable seems more correct to use to store some data. Commented Aug 2, 2016 at 3:38
  • 1
    It is an instance variable! Any variable in an instance's namespace is an instance variable --- it doesn't matter how it got there. Commented Aug 2, 2016 at 4:50
  • These terms are really confusing... Commented Aug 2, 2016 at 5:31

1 Answer 1

3

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'
Sign up to request clarification or add additional context in comments.

3 Comments

So, can I say that a more standard way when creating a class, I have to put initialize instance variables in init, because when c = Car() have some instance variables but another d = Car() does not which would be really inconsistent?
Yes, that's correct. That way every instance of Car will have those attributes "spring into existence" since "they are first assigned to" in __init__.
"dynamic attributes" are just instance attributes. There is no special status for attributes not assigned in __init__.

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.