我在理解类/实例变量在Python中的工作方式时遇到了问题。我不明白为什么当我尝试这个代码时,list变量似乎是一个类变量
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']
答案 0 :(得分:44)
这是因为Python使用.
解析名称的方式。当您编写self.list
时,Python运行时首先尝试通过在实例对象中查找它来解析list
名称,如果在那里找不到它,那么在类实例中。
让我们一步一步地研究它
self.list.append(1)
list
中是否有self
个名称?
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
引用可以看到类名。
答案 1 :(得分:5)
Python有关于查找名称的有趣规则。如果您真的想弯曲,请尝试以下代码:
class testClass():
l = []
def __init__(self):
self.l = ['fred']
这将为每个实例提供一个名为l
的变量,用于屏蔽类变量l
。如果你self.__class__.l
,你仍然可以获得类变量。
我想到的方式就是这样......每当你做instance.variable
时(即使对于方法名称,它们只是变量的值恰好是函数)它会在实例的字典中查找它。如果它找不到它,它会尝试在实例的类字典中查找它。这仅在变量被“读取”时才有效。如果它被分配给它,它总是在实例字典中创建一个新条目。
答案 2 :(得分: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']
答案 3 :(得分:0)
实例化类时,会自动执行__init__
方法。
在第一种情况下,您的列表是一个类属性,并由其所有实例共享。你得到了两件事,因为你在p
瞬时附加了一个,而在实例化f
时附加了另一个(第一个已经在第一次调用时附加了第一个)。