美文网首页
python 对象污染

python 对象污染

作者: HoPGoldy | 来源:发表于2020-05-20 15:47 被阅读0次

问题

最近在用 py3 写一个小脚本,结果遇到了一个问题:不同对象实例对内部属性的操作居然会相互影响。如下,创建实例test1时的修改居然“蔓延”到了另一个实例test2上:

class Test:
    inter_val = []

    def __init__(self, num):
        for i in range(num):
            self.inter_val.append(i)
    
        print(self.inter_val)


if __name__ == "__main__":
    test1 = Test(10)
    test2 = Test(10)

执行结果:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

原因

导致这个问题出现的根本原因其实是 python 的万物皆对象。可以看到,内部属性inter_val是在声明时就直接分配了内存空间。而在__init__中直接对其进行操作。这么做乍一看没什么问题,但是实际上,所有由Test类实例化的对象中的inter_val数组都指向了同一片内存空间!

通过下面的代码可以更好的理解这个问题:

class Test:
    inter_val = []

    def __init__(self, num):
        # 这里不做操作而是打印其内存地址
        print(id(self.inter_val))


if __name__ == "__main__":
    test1 = Test(10)
    test2 = Test(10)

执行输出

139670768852872
139670768852872

可以看到,两个不同实例的inter_val完全是同一个数组。不仅如此,所有的复杂类型,如字典、对象等都是这样。只要不是直接对inter_val进行赋值,都会出现这个问题

解决方法

至于解决的办法很简单,那就是在__init__里对需要的属性进行初始化,或者直接啥时候用啥时候初始化,如下:

class Test:
    # 不分配空间
    inter_val = None

    def __init__(self, num):
        # 实例化时再分配内存
        self.inter_val = []
        for i in range(num):
            self.inter_val.append(i)
    
        print(self.inter_val)


if __name__ == "__main__":
    test1 = Test(10)
    test2 = Test(10)

然后就可以看到输出正常了:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

当然,这么做就需要多注意对象属性的空值检查,防止一不小心访问到了None

相关文章

  • python 对象污染

    问题 最近在用 py3 写一个小脚本,结果遇到了一个问题:不同对象实例对内部属性的操作居然会相互影响。如下,创建实...

  • python对象和垃圾回收

    1. python对象 python使用对象模型来存储数据,python中万物皆对象。python对象有三个特性:...

  • python基础-02

    Python 面向对象 python是一门面向对象的语言 Python内置类属性 python对象销毁(垃圾回收)...

  • 2019-10-23

    python面向对象编程总结 python中的对象:在其...

  • Python 面向对象编程

    Python 面向对象编程(一) Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象...

  • python面向对象学习笔记-01

    学习笔记 # 0,OOP-Python面向对象 - Python的面向对象 - 面向对象编程 - 基础 -...

  • Python进阶1

    Python中一切皆对象 引言 Java语言也是面向对象的语言,但是Python要更加彻底 Python的面向对象...

  • 关于 Python 中的 for 问题

    Python 2 和 Python 3 中的 for 有一点不一样 Python 2 中的 for 循环会污染全局...

  • Python浅拷贝 深拷贝

    内存泄漏太可怕。 Python 可变对象 & 不可变对象 在Python中,对象分为两种:可变对象和不可变对象。 ...

  • Python入门-对象类型

    Python语言中,数据以对象的形式出现,无论是Python提供的内置对象,还是使用Python语言创建的对象。 ...

网友评论

      本文标题:python 对象污染

      本文链接:https://www.haomeiwen.com/subject/xkhnohtx.html