为什么Python不使用类似C++/Java的语法来定义实例变量?

Tom*_*mmy 4 python java class instance-variables

这困扰了我几个小时,因为我来自C++世界.我终于知道发生了什么,但我不知道为什么这是默认行为.我想了解为什么语言是这样设计的.

我想要一个实例变量mem.所以我尝试了这个:

class x(object):
   mem = []

obj = x()
obj.mem.append(1)
print(obj.mem)
objTWO = x()
objTWO.mem.append(2)
print(objTWO.mem)
Run Code Online (Sandbox Code Playgroud)

打印这个:

[1] 

[1, 2]
Run Code Online (Sandbox Code Playgroud)

鉴于:

class x(object):

    def __init__(self):
        self.mem = []

obj = x()
obj.mem.append(1)
print(obj.mem)
objTWO = x()
objTWO.mem.append(2)
print(objTWO.mem)
Run Code Online (Sandbox Code Playgroud)

版画

[1]

[2]
Run Code Online (Sandbox Code Playgroud)

为什么第一个是默认行为?这里的直觉是什么,因为它与多少主流OO语言的工作方式相反(他们static为顶级案例引入了关键字,这让你明确地说你想要一个静态变量)?对于Python的新手来说,这是一个惊喜.

此外,似乎您可以拥有一个实例变量和一个具有相同名称的类变量:

class x(object):
    mem = []

    def __init__(self):
        self.mem = []
Run Code Online (Sandbox Code Playgroud)

我必须运行它来弄清楚要打印的内容.我甚至无法猜到!

sen*_*rle 8

直觉是在Python中,一切都是对象,包括类本身.在Python中没有"静态"关键字这样的东西; 有类,它们是对象,这些类有属性.类定义中出现的所有内容都是类属性 - 包括方法和其他类型的属性.

这种设计的好处是简单性和一致性.公共或私有,或静态和非静态属性之间没有区别.类和实例属性之间的区别通过类构造函数自然出现.当__init__调用(间接通过ClassName(params))时,它通过self参数接收类的新实例,然后直接修改该实例.一切都是通过已经定义的构造明确地发生 - 您不必理解任何新语法或新关键字来查看创建实例时发生的情况.

然后你必须要了解的是Python的属性查找模型.它的工作方式几乎与PATH大多数炮弹的分辨率相同.例如,在bash中执行命令(ls)时,将搜索路径中的第一个条目,然后搜索第二个条目,依此类推,找到的命令的第一个版本是执行的命令.但在这种情况下,路径看起来像这样(至少在单继承的简单情况下):

instance; class; superclass; superclass; ... and so on
Run Code Online (Sandbox Code Playgroud)

这与c或c ++中嵌套作用域中的名称解析没有太大区别.你抱怨:

更糟糕的是,您似乎可以拥有一个实例变量和一个具有相同名称的类变量.

但这真的比c允许你int i;在一个块中定义,创建一个内部块,然后定义另一个int i;掩盖原始的事实更令人困惑吗?