python两个实例类之间会有干扰吗?

就如下述代码所示,我新建两个类,修改其中一个,为什么list a就受到了test1的影响,而int
b却没有收到影响???

class test :
    a = []
    b = 0
def main():
    #实例化两个类,两个之间没有关系。
    test1 =test()
    test2 =test()
    
    #这里我只对test1进行了操作
    test1.a.append('123')
    test1.b =567
    
    #期望这里的test2应该是没有[]和0
    print(test2.a)
    print(test2.b)

if __name__ == "__main__":
    main()

这是什么原因???我看了基础语法教程也没说到这块有什么特殊的地方啊?

阅读 3.6k
2 个回答

这里涉及两个 Python 知识点:

  • 类级共享属性
  • 容器
  1. 这样的写法,属性是类级共享的:

    class Spam:
      foo = []
      bar = 11
  2. 字典、列表等是容器类型;添加或删除元素操作,是操作容器内的元素

    >>> egg = []
    >>> hex(id(egg))
    '0x1050d3cc0'
    >>> egg.extend([4, 5, 6])
    >>> egg
    [4, 5, 6]
    >>> hex(id(egg))
    '0x1050d3cc0'
    >>> 
    >>> egg = [4, 5, 6]
    >>> egg
    [4, 5, 6]
    >>> hex(id(egg))
    '0x10514f280'

这两点合在一起就是你描述的问题。

关于类级共享属性,当实例化一个类之后,这个实例还是和类使用共享的属性:

>>> class Spam:
...   foo = []
...   bar = 11
...
>>> hex(id(Spam.foo))
'0x1050ada80'
>>> s = Spam()
>>> hex(id(s.foo))
'0x1050ada80'

只有当实例对属性赋值之后,这个属性的作用范围就只在这个实例内部(相当于在实例内重新创建了一个该属性)。

>>> s.foo is Spam.foo
True
>>> s.foo = [1, 2, 3]
>>> hex(id(s.foo))
'0x105111200'
>>> s.foo is Spam.foo
False

这真是python特色问题了,搜一下“python 可变对象”。
简单来说,列表字典等属于可变对象,当他们作为函数参数/类变量时,如果发生改写,是不会生成新对象的。而int等不可改写对象正好相反。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题