我有一个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'
所以我的问题是:两种情况究竟发生了什么,有什么区别?
答案 0 :(得分:7)
不,这是两件不同的事情。
在Python中,一切都是对象。类是对象,函数是对象,实例是对象。由于一切都是对象,所以一切都以类似的方式运行。在您的情况下,您创建一个类实例(==具有类型“Class”的对象),名称为“pytest”。该对象有两个属性:i
和fuc
。 i
是“整数”或“数字”的实例,fuc
是“函数”的实例。
当你使用“pytest.j”时,你告诉python“查找对象pytest
,当你拥有它时,查找i
”。 “pytest”是一个类实例,但这并不重要。
当您创建“pytest”实例(==具有“pytest”类型的对象)时,您有一个具有“默认值”的对象。在您的情况下,a
是pytest
的一个实例,这意味着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首先检查该对象的实例变量,然后检查该对象类型的类变量。类变量用作实例变量的默认值。