python class's attribute not in __init__

江枫思渺然 提交于 2019-12-08 06:36:09

问题


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.


回答1:


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'


来源:https://stackoverflow.com/questions/38710765/python-classs-attribute-not-in-init

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!