访问实例属性和类属性之间的区别

时间:2009-08-20 08:48:48

标签: python class instance

我有一个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'

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

2 个答案:

答案 0 :(得分:7)

不,这是两件不同的事情。

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

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

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

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

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

答案 1 :(得分:0)

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

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首先检查该对象的实例变量,然后检查该对象类型的类变量。类变量用作实例变量的默认值。