这困扰了我几个小时,因为我来自 C++ 世界。我终于知道发生了什么,但我不知道为什么这是默认行为。我想了解为什么这种语言是这样设计的。
我想要一个实例变量mem
。所以我尝试了这个:
class x(object):
mem = []
obj = x()
obj.mem.append(1)
print(obj.mem)
objTWO = x()
objTWO.mem.append(2)
print(objTWO.mem)
打印这个:
[1]
[1, 2]
鉴于:
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)
打印
[1]
[2]
为什么第一个是默认行为?这里的直觉是什么,因为它与许多主流 OO 语言的工作方式相反(它们为顶级情况引入了 static
关键字,这让你明确地说你想要一个静态变量)?对于 Python 新手来说,这是一个惊喜。
此外,您似乎可以拥有同名的实例变量和类变量:
class x(object):
mem = []
def __init__(self):
self.mem = []
我必须运行它才能确定要打印的内容。我什至猜不到!
最佳答案
直觉是,在 Python 中,一切 都是对象,包括类本身。 Python 中没有“static”关键字这样的东西;有类,是对象,那些类有属性。 出现在类定义中的所有内容 都是类属性——包括方法和其他类型的属性。
这种设计的好处是简单和一致。公共(public)或私有(private)之间没有区别,静态和非静态属性之间也没有区别。类和实例属性之间的区别通过类构造函数自然而然地出现。当__init__
被调用(间接通过 ClassName(params)
),它通过 self
接收该类的新实例参数,然后它直接修改该实例。一切都通过已经定义的构造显式发生——您无需了解任何新语法或新关键字即可查看创建实例时发生的情况。
那么你只需要了解 Python 的属性查找模型即可。它的工作原理几乎与 PATH
相同大多数外壳的分辨率。例如,在 bash 中,当您执行命令 ( ls
) 时,会搜索路径中的第一个条目,然后是第二个条目,依此类推,找到的第一个版本的命令就是执行的版本。但在这种情况下,路径看起来像这样(至少在具有单一继承的简单情况下):
instance; class; superclass; superclass; ... and so on
这与 c 或 c++ 中嵌套作用域中的名称解析并没有太大区别。你提示:
Even worse is that it seems you are allowed to have an instance variable and a class variable with the same name.
但这真的比 c 允许您定义 int i;
更令人困惑吗?在一个 block 中,创建一个内部 block ,然后定义另一个 int i;
掩盖原来的?
关于java - 为什么 Python 不使用类 C++/Java 的语法来定义实例变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13385194/