Python中的可变对象与不可变对象

yizhihongxing

Python中所有类型的值都是对象,这些对象分为可变对象与不可变对象两种:

  • 不可变类型

    floatintstrtupleboolfrozensetbytes

    tuple自身不可变,但可能包含可变元素,如:([3, 4, 5], 'tuple')

  • 可变类型

    listdictsetbytearray自定义类型

 

+=操作符

+=操作符对应__iadd__魔法方法,对于不可变对象a+=ba=a+b等价,对于可变对象并不等价,dictset不支持+=和+操作符。

l1 = l2 = [1, 2, 3]
# 只有l1发生变化
# l1 = l1 + [4]
# l1和l2都发生变化,输出[1, 2, 3, 4, 5]
l1 += [4, 5]
print(l1)
print(l2)

 

浅拷贝 深拷贝

与赋值不同,拷贝(可能)会产生新的对象,可通过拷贝来避免不同对象间的相互影响。

在Python中,不可变对象,浅拷贝和深拷贝结果一样,都返回原对象:

import copy
​
​
t1 = (1, 2, 3)
t2 = copy.copy(t1)
t3 = copy.deepcopy(t1)
print(t1 is t2) # True
print(t1 is t3) # True
print(id(t1), id(t2), id(t3)) # 输出相同值

对于可变对象,则会产生新对象,只是若原对象中存在可变属性/字段,则浅拷贝产生的对象的属性/字段引用原对象的属性/字段,深拷贝产生的对象和原对象则完全独立:

l1 = [1, 2, 3]
l2 = l1.copy()
print(l1 is l2)  # False
l2[0] = 100
print(l1[0])  # 1

 

import copy
​
​
class Id:
    def __init__(self, name):
        self.name = name
​
​
class Person:
    def __init__(self, id: Id):
        self.id = id
​
​
p1 = Person(Id("eason"))
p2 = copy.copy(p1)
print(p1 is p2)  # False
print(p1.id is p2.id)  # True
p2.id.name = "p2"
print(p1.id.name)  # p2
​
p3 = copy.deepcopy(p1)
print(p1 is p3)  # False
print(p1.id is p3.id)  # False
print(p1.id.name is p3.id.name)  # True,字符串不可变,这里name属性的地址一样
p3.id.name = "p3"
print(p1.id.name)  # 还是p2

 

Python中可使用以下几种方式进行浅拷贝:

  • 使用copy模块的copy方法

  • 可变类型切片

    l1 = [1, 2, 3]
    l2 = l1[:]
    print(l1 is l2)  # False

     

  • 可变类型的copy方法

    [].copy()
    {}.copy()
    set().copy()

     

  • 调用list, set, dict方法

    l1 = [1, 2, 3]
    l2 = list(l1)
    l2[0] = 100
    print(l1[0])  # 1

     

  • 推导式

    列表、字典、集合推导式

    class Person:
        def __init__(self, name):
            self.name = name
    ​
    ​
    l1 = [Person("l1")]
    l2 = [i for i in l1]
    print(l1 is l2)  # False
    print(l1[0] is l2[0])  # True
    ​
    s1 = {Person("s1")}
    s2 = {i for i in s1}
    print(s1 is s2)  # False
    ​
    ele1 = s1.pop()
    ele2 = s2.pop()
    print(ele1 is ele2)  # True

     

推荐阅读

Different behaviour for list.__iadd__ and list.__add__

学习Python一年,这次终于弄懂了浅拷贝和深拷贝

copy — Shallow and deep copy operations

原文链接:https://www.cnblogs.com/Cwj-XFH/p/17308499.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python中的可变对象与不可变对象 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • python调用系统中应用程序的函数示例

    让我们来详细讲解一下”python调用系统中应用程序的函数示例”的完整攻略。 1. 使用Python的os模块 Python的os模块提供了一种调用系统中应用程序的函数方式: import os os.system("应用程序文件路径 参数") 说明: 应用程序的文件路径:要调用的应用程序在计算机上的路径 参数:输入到应用程序的参数,如果…

    python 2023年5月30日
    00
  • python不同系统中打开方法

    当在不同的操作系统中运行Python程序时,文件路径格式和文件的打开方式可能会有所不同。下面是一些在不同操作系统中打开文件的方法。 Windows系统中打开文件 在Windows中,文件路径用反斜杠“\”来表示。为了避免路径被转义,可以在路径之前添加“r”前缀。 使用open()函数来打开文件,可以指定打开文件的模式,例如读模式(’r’)和写模式(’w’)。…

    python 2023年5月30日
    00
  • Python手写回归树的实现

    Python手写回归树的实现攻略 简介 回归树是一种常用的回归挖掘技术,其基本思想是通过对样本数据的递归划分来建立模型,对于每一次的划分都是基于当前样本集中的某一个特征,根据该特征分裂为若干子集,使得每个子集的目标值尽可能的接近,最终达到建立决策树模型的目的。在本文中,我们将使用 Python 语言手写一个回归树模型,并使用两个实例来说明其基本使用方法和实现…

    python 2023年6月3日
    00
  • 使用python写一个自动浏览文章的脚本实例

    使用Python编写自动浏览文章的脚本可以使用Selenium库来模拟用户的行为,这样可以避免繁琐的手动操作,提高效率。 下面是简单的步骤: 安装Selenium库 使用pip安装Selenium库,打开命令行窗口输入以下命令: pip install selenium 安装浏览器驱动程序 Selenium需要使用浏览器驱动程序来模拟用户对浏览器的操作。需要…

    python 2023年5月19日
    00
  • 使用python装饰器计算函数运行时间的实例

    使用Python装饰器计算函数运行时间是一个比较常见的问题。下面是对如何实现这个功能的详细攻略。 装饰器的基本理解 装饰器本质上是一个Python函数,它可以在不改变原始函数的情况下,添加一些额外的功能,例如日志记录、缓存结果,以及计算函数的运行时间。 装饰器使用“@”符号作为语法糖,放置在要被装饰的函数前面。下面是一个简单的计算函数运行时间的装饰器实现: …

    python 2023年6月3日
    00
  • python中的split()函数和os.path.split()函数使用详解

    Python中的split()函数使用详解: split()是Python的字符串函数之一,用于将字符串分割并生成一个分割后的字符串列表。该函数的参数sep表示分割符,默认为空白字符。如果没有分隔符,会将整个字符串视为单一元素存入列表,并返回一个只包含一个元素的列表。下面是使用split()的例子: s = "Hello, World" …

    python 2023年6月2日
    00
  • python实现可以断点续传和并发的ftp程序

    下面是 Python 实现可以断点续传和并发的 FTP 程序的完整攻略: 1. 确认 FTP 服务器地址和端口 在开始编写 Python 脚本之前,需要确认需要连接的 FTP 服务器地址和端口。可以通过访问 FTP 服务器的网页或者询问管理人员来获取这些信息。 2. 安装 Python FTP 包 Python 自带的 ftplib 库提供了很好的 FTP …

    python 2023年6月2日
    00
  • python基于gevent实现并发下载器代码实例

    Python基于gevent实现并发下载器代码实例 在Python中,我们可以使用gevent库实现并发下载器。gevent是一个基于协程的Python网络库,可以帮助我们更轻松地实现并发下载器。本文将介绍如何使用Python和gevent实现并发下载器,并提供两个示例代码。 步骤1:安装gevent库 在使用gevent库之前,我们需要先安装它。可以使用p…

    python 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部