3 回答
TA贡献1853条经验 获得超18个赞
这是因为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引用看到类名称。
TA贡献1876条经验 获得超6个赞
Python有关于查找名称的有趣规则。如果您真的想改变主意,请尝试以下代码:
class testClass():
l = []
def __init__(self):
self.l = ['fred']
这将给每个实例一个变量l,该变量将屏蔽类变量l。如果这样做,您仍然可以使用class变量self.__class__.l。
我的想法是……只要您这样做instance.variable(即使对于方法名,它们只是值恰好是函数的变量),它都会在实例的字典中查找它。如果找不到它,它将尝试在实例的“类”字典中查找它。仅当变量被“读取”时。如果将其分配给它,它将始终在实例字典中创建一个新条目。
TA贡献1872条经验 获得超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']
添加回答
举报