【问题标题】:Difference between accessing an instance attribute and a class attribute访问实例属性和类属性的区别
【发布时间】:2010-11-21 06:00:35
【问题描述】:

我有一个 Python 类

class pytest:
    i = 34
    def func(self):
        return "hello world"

当我访问pytest.i 时,我得到 34。我也可以通过其他方式做到这一点:

a = pytest()
a.i

这也给出了 34。

如果我尝试访问(不存在的)pytest.j,我会得到

Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
pytest.j
AttributeError: class pytest has no attribute 'j'

当我尝试a.j 时,错误是

Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
a.j
AttributeError: pytest instance has no attribute 'j'

所以我的问题是:这两种情况到底发生了什么,有什么区别?

【问题讨论】:

    标签: python class instance


    【解决方案1】:

    不,这是两个不同的东西。

    在 Python 中,一切都是对象。类是对象,函数是对象,实例是对象。因为一切都是对象,所以一切都以类似的方式表现。在您的情况下,您创建一个名为“pytest”的类实例(== 一个类型为“Class”的对象)。该对象有两个属性:ifuci 是“整数”或“数字”的实例,fuc 是“函数”的实例。

    当你使用“pytest.j”时,你告诉python“查找对象pytest,当你拥有它时,查找i”。 “pytest”是一个类实例,但这并不重要。

    当您创建“pytest”实例(== 类型为“pytest”的对象)时,您将拥有一个具有“默认值”的对象。在您的情况下,apytest 的一个实例,这意味着在a 中找不到的任何内容都将在pytest 中搜索,接下来。

    所以a.j 的意思是:“查看a。当它不存在时,也查看pytest”。但是j 不存在,Python 现在必须给你一个有意义的错误信息。它可以说“类pytest没有属性'j'”。这将是正确但毫无意义的:您必须自己弄清楚您试图通过a 访问j。这会令人困惑。 Guido 不会有那个。

    因此,python 使用不同的错误消息。由于它并不总是有实例的名称 (a),因此设计者决定改用该类型,因此您会得到“pytest instance...”。

    【讨论】:

      【解决方案2】:

      总而言之,与类和对象相关的变量有两种类型:类变量和实例变量。类变量与类相关联,但实例变量与对象相关联。这是一个例子:

      class TestClass:
          classVar = 0
          def __init__(self):
              self.instanceVar = 0
      

      classVar 是与类TestClass 关联的类变量。 instanceVar 是与 TestClass 类型的对象关联的实例变量。

      print(TestClass.classVar) # prints 0
      instance1 = TestClass() # creates new instance of TestClass
      instance2 = TestClass() # creates another new instance of TestClass
      

      instance1 和instance2 共享classVar,因为它们都是TestClass 类型的对象。

      print(instance1.classVar) # prints 0
      TestClass.classVar = 1
      print(instance1.classVar) # prints 1
      print(instance2.classVar) # prints 1
      

      但是,它们都有 instanceVar 的副本,因为它是与单个实例相关联的实例变量,而不是类。

      print(instance1.instanceVar) # prints 0
      print(TestClass.instanceVar) # error! instanceVar is not a class variable
      instance1.instanceVar = 1
      print(instance1.instanceVar) # prints 1
      print(instance2.instanceVar) # prints 0
      

      正如 Aaron 所说,如果您尝试访问一个实例变量,Python 首先检查该对象的实例变量,然后检查该对象类型的类变量。类变量用作实例变量的默认值。

      【讨论】:

        猜你喜欢
        • 2018-04-14
        • 2021-12-26
        • 1970-01-01
        • 1970-01-01
        • 2015-09-10
        • 1970-01-01
        • 2011-12-01
        • 2011-11-24
        相关资源
        最近更新 更多