python类实例变量和类变量

jon*_*opf 28 python variables class instance

我在理解类/实例变量如何在Python中工作时遇到了问题.我不明白为什么当我尝试这个代码时,list变量似乎是一个类变量

class testClass():
    list = []
    def __init__(self):
        self.list.append('thing')

p = testClass()
print p.list

f = testClass()
print f.list
Run Code Online (Sandbox Code Playgroud)

输出:

['thing']
['thing', 'thing']
Run Code Online (Sandbox Code Playgroud)

当我这样做时,它似乎是一个实例变量

class testClass():
    def __init__(self):
        self.list = []
        self.list.append('thing')

p = testClass()
print p.list

f = testClass()
print f.list
Run Code Online (Sandbox Code Playgroud)

输出:

['thing']
['thing']
Run Code Online (Sandbox Code Playgroud)

rod*_*igo 47

这是因为Python解析名称的方式..当你编写self.listPython运行时尝试list首先通过在实例对象中查找它来解析名称,如果在那里找不到它,那么在类实例中.

让我们一步一步地看一下

self.list.append(1)
Run Code Online (Sandbox Code Playgroud)
  1. list对象中有名字self吗?
    • 是的:使用它!完.
    • 不:转到2.
  2. list对象的类实例中是否有名称self
    • 是的:使用它!完
    • 不:错误!

但是当你绑定一个名字时,事情是不同的:

self.list = []
Run Code Online (Sandbox Code Playgroud)
  1. 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
Run Code Online (Sandbox Code Playgroud)

这将打印:

['thing']
['foo']
['foo']
Run Code Online (Sandbox Code Playgroud)

删除实例名称的那一刻,通过self引用可以看到类名.


Omn*_*ous 5

Python有关于查找名称的有趣规则.如果您真的想弯曲,请尝试以下代码:

class testClass():
    l = []
    def __init__(self):
        self.l = ['fred']
Run Code Online (Sandbox Code Playgroud)

这将为每个实例提供一个名为l掩盖类变量的变量l.如果你这样做,你仍然可以获得类变量self.__class__.l.

我想到的方式就是这样......每当你这样做时instance.variable(即使对于方法名称,它们只是变量的值恰好是函数)它会在实例的字典中查找它.如果它找不到它,它会尝试在实例的类字典中查找它.这仅在变量被"读取"时才有效.如果它被分配给它,它总是在实例字典中创建一个新条目.