【问题标题】:python class's attribute not in __init__python类的属性不在__init__中
【发布时间】:2016-08-02 02:11:40
【问题描述】:

我想知道为什么以下代码有效?

#!/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)

无意中发现init中不用初始化属性。我向每位导师学习,我必须将作业放入 init 中,如下所示。

#!/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)

如果有官方文档能解释一下就更好了。

【问题讨论】:

  • 你看过Python教程中关于Classes的官方文档吗:docs.python.org/3/tutorial/classes.html
  • 数据属性对应于 Smalltalk 中的“实例变量”和 C++ 中的“数据成员”。数据属性不需要声明;像局部变量一样,它们在首次分配给它们时就立即存在
  • 但是我也想知道,在实践中,这个特性是用来做什么的?它不是类变量,因此不能共享。看起来它是用来存储一些值的,如果它是用来存储一些数据的,为什么不使用实例变量呢?实例变量似乎更适合用于存储一些数据。
  • 一个实例变量!实例命名空间中的任何变量都是实例变量——不管它是如何到达那里的。
  • 这些术语真的很混乱......

标签: python class variable-assignment


【解决方案1】:

这是类属性 vs 实例属性 vs 动态属性。当你这样做时:

class Car():
    def __init__(self):    
        pass

c = Car()
c.speed = 3
c.time = 5

speedtime 是动态属性(不确定这是否是官方术语)。如果类的用法是在调用Car 的任何其他方法之前设置这些属性,那么这些方法可以使用self.speed。否则会报错:

>>> d = Car()
>>> d.speed
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute 'speed'
>>>

发生这种情况是因为对于c,速度和时间是Car 实例的属性。它们的存在或价值不会在 Car 的其他实例中传播。因此,当我创建d 然后尝试查找d.speed 时,该属性不存在。正如您在自己的评论中所说,“它们在第一次被分配时就存在了。”

无意中发现在init中不用初始化属性。我向每位导师学习,我必须像下面这样将作业放入 init 中。

你的导师大错特错,或者你误解了他们的意思。在您给出的示例中,每辆汽车都有相同的初始 speedtime。通常,__init__ 看起来像这样:

class Car():
    def __init__(self, speed, time):  # notice that speed and time are
                                      # passed as arguments to init
        self.speed = speed
        self.time = time

然后您可以使用:c = Car(3, 5) 初始化 Car。或者如果它是可选的,则将默认值放入 init 中。

编辑:示例改编 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'

【讨论】:

  • 那么,我可以说一个更标准的创建类的方式,我必须把初始化实例变量放在init中,因为当c = Car()有一些实例变量,但另一个 d = Car() 没有,这真的不一致吗?
  • 是的,没错。这样,Car 的每个实例都将具有这些属性,因为“它们首先被分配给”__init__
  • “动态属性”只是实例属性。 __init__ 中未分配的属性没有特殊状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 2011-10-27
  • 2015-12-08
  • 1970-01-01
  • 2011-04-25
  • 2011-06-16
  • 2018-02-23
相关资源
最近更新 更多