python 类实例变量和类变量
- 2025-01-16 08:38:00
- admin 原创
- 103
问题描述:
我无法理解 Python 中的类/实例变量是如何工作的。我不明白为什么当我尝试这段代码时,列表变量似乎是一个类变量
class testClass():
list = []
def __init__(self):
self.list.append('thing')
p = testClass()
print p.list
f = testClass()
print f.list
输出:
['thing']
['thing', 'thing']
当我这样做时,它似乎是一个实例变量
class testClass():
def __init__(self):
self.list = []
self.list.append('thing')
p = testClass()
print p.list
f = testClass()
print f.list
输出:
['thing']
['thing']
解决方案 1:
这是因为 Python 使用 来解析名称的方式.
。编写时,self.list
Python 运行时首先尝试list
通过在实例对象中查找来解析名称,如果在那里找不到,则在类实例中查找。
让我们一步一步来看一下
self.list.append(1)
list
该物体有名字吗self
?
* 是的:使用它!完成。
* 否:转至2。
list
对象的类实例中是否有名称self
?
* 是的:使用它!完成
* 否:错误!
但是当你绑定一个名称时,事情就不同了:
self.list = []
list
该物体有名字吗self
?
* 是的:覆盖它!
* 否:绑定它!
所以,这始终是一个实例变量。
第一个例子list
在类实例中创建了一个,因为这是当时的活动范围(不在self
任何地方)。但第二个例子list
在的范围内明确创建了一个self
。
更有趣的是这个例子:
class testClass():
list = ['foo']
def __init__(self):
self.list = []
self.list.append('thing')
x = testClass()
print x.list
print testClass.list
del x.list
print x.list
这将打印:
['thing']
['foo']
['foo']
删除实例名称后,类名可通过self
引用查看。
解决方案 2:
Python 在查找名称方面有有趣的规则。如果您真的想改变一下思维,请尝试以下代码:
class testClass():
l = []
def __init__(self):
self.l = ['fred']
这将为每个实例提供一个变量,l
该变量会屏蔽类变量l
。如果您这样做,您仍然可以获取类变量self.__class__.l
。
我的想法是这样的...每当你这样做时instance.variable
(即使是方法名,它们也只是变量,其值恰好是函数),它都会在实例的字典中查找它。如果它在那里找不到它,它会尝试在实例的类字典中查找它。这仅在变量被“读取”时才会发生。如果正在分配它,它总是在实例字典中创建一个新条目。
解决方案 3:
在您的第一个示例中,list
是类的一个属性,由其所有实例共享。这意味着您甚至可以在没有类型对象的情况下访问它testClass
:
>>> class testClass():
... list = []
... def __init__(self):
... self.list.append("thing")
...
>>> testClass.list
[]
>>> testClass.list.append(1)
>>> testClass.list
[1]
但是所有对象都list
与类以及彼此共享属性:
>>> testObject = testClass()
>>> testObject.list
[1, 'thing']
>>> testClass.list
[1, 'thing']
>>>
>>> testObject2 = testClass()
>>> testClass.list
[1, 'thing', 'thing']
>>> testObject2.list
[1, 'thing', 'thing']
解决方案 4:
当你实例化一个类时,__init__
方法会自动执行。
在第一种情况下,您的列表是类属性,并由其所有实例共享。您有两个“事物”,因为您在实例化时附加了一个p
,在实例化时附加了另一个f
(第一个已经在第一次调用时附加)。