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)
我必须运行它来弄清楚要打印的内容.我甚至无法猜到!
直觉是在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;
掩盖原始的事实更令人困惑吗?