Python比较操作符、变量赋值、对象拷贝

1. 比较操作符 == 和 is

1.1 区别
  • == 操作符比较对象之间的值是否相等
  • is 操作符比较的是对象的身份标识是否相等,即是否是同一个对象,是否指向同一个内存地址
  • is 操作符的速度效率通常要优于==,因为is操作符不能被重载,执行is操作只是简单的获取对象的ID,并进行比较,而等于操作符则会递归地遍历对象所有值,并逐一比较
  • 当比较一个变量与一个单例时,通常使用is
1.2 实例
# 比较两个对象
def compare(A, B):
if A == B:
print(f"{A} == {B}:{True}")
else:
print(f"{A} == {B}:{False}")
if A is B:
print(f"{A} is {B}:{True}")
else:
print(f"{A} is {B}:{False}")
print(id(A), id(B))
A = -7
B = -7
compare(A, B)
C = 4
D = 4
compare(C, D)
"""
python内部对**-5到256的整型**维持一个数组,起到一个缓存的作用,使得性能优化,因此,在-5到256之间的整型数字比较,都相等。上述代码是在jupyter notebook中运行的,如果在pycharm中运行,则都是True,pycharm中做了优化。
"""
-7 == -7:True
-7 is -7:False
139667038587504 139667038587152
4 == 4:True
4 is 4:True
# 比较一个变量
if a is None:
... if a is not None:
...

2. 变量及其赋值

2.1 概念和逻辑关系
  • 变量的赋值,只是表示让变量指向了某个对象,并不表示拷贝对象给变量;而一个对象,可以被多个变量所指向。

  • 可变对象(列表,字典,集合等等)的改变,会影响所有指向该对象的变量。

  • 对于不可变对象(字符串、整型、元组等等),所有指向该对象的变量的值总是一样的,也不会改变。但是通过某些操作(+= 等等)更新不可变对象的值时,会返回一个新的对象

  • 变量可以被删除,但是对象无法被删除,需要通过python垃圾回收机制回收。

2.2 Python函数的参数传递

​ 是赋值传递,python里所有的数据类型都是对象,所以参数传递时,只是让让新变量与原变量指向相同的对象而已,并不存在值传递或是引用传递(c++等语言中)一说。

2.3 思考题

2.3.1 变量指向的是同一个对象吗?——查id

# l1,l2,分别分配了内存空间,不是指向同一个对象
# l2,l3,是指向
l1 = [1, 2, 3] # 创建了新对象
l2 = [1, 2, 3] # 创建了新对象
l3 = l2 # 指向同一个对象
print(id(l1), id(l2), id(l3))
# 1479611736648 1479611736712 1479611736712

2.3.2 变量被修改了吗?

# 字典是可变对象,对象改变,会影响所有指向该对象的变量
def func(d):
d['a'] = 10
d['b'] = 20
d = {'a': 1, 'b': 2}
func(d)
print(d) # {'a': 10, 'b': 20}

3. 浅拷贝和深度拷贝

3.1 浅拷贝概念

浅拷贝是指重新分配一块内存,创建一个新的对象,里面的元素是原对象内第一层对象的引用,因此,如果原对象中的元素是可变的,改变其也会影响拷贝后的对象,存在一定的副作用。

3.2 浅拷贝方法——可变对象
  • 类型工厂函数:

    • 是指不通过类而是通过函数来创建对象,list(),set(),int(),dict(),tuple(),str()等数据类型本身的构造器
    • 浅拷贝中适用的是可变对象,因此,list(),set(),dict()适用,其余不适用
  • 切片操作:列表
  • copy模块中copy方法:copy.copy()
3.3 深度拷贝概念

深度拷贝是指重新分配一块内存,创建一个新的对象,并且将元对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中,因此,新对象和原对象没有任何关联。另外,深度拷贝中会维护一个字典,记录已经拷贝的对象及其ID,来提高效率并放置无限递归的发生。

3.4 深度拷贝方法
  • copy模块中的deepcopy方法:copy.deepcopy()
3.5 实例
3.5.1 浅拷贝和赋值的区别——是否会创建一个新对象
l1 = [1, 2, 3]
l2 = list(l1) # 使用工厂函数实现浅拷贝
compare(l1, l2)
a = [1, 2, 3]
b = a # 变量赋值
compare(a, b)
[1, 2, 3] == [1, 2, 3]:True
[1, 2, 3] is [1, 2, 3]:False
140603550652928 140603550660720
[1, 2, 3] == [1, 2, 3]:True
[1, 2, 3] is [1, 2, 3]:True
3.5.2 字符串、数字不能实现拷贝
import copy
t1 = 4
t2 = copy.deepcopy(t1) # 对一个元组实现深度拷贝
compare(t1, t2)
sr1 = "adc"
sr2 = str(sr1) # 字符串不能创建浅拷贝
compare(sr1, sr2)
4 == 4:True
4 is 4:True
adc == adc:True
adc is adc:True
3.5.3 元组的浅拷贝和深度拷贝
import copy
s1 = (1, 2, 3,[1,2])
s2 = copy.copy(s1) # 元组不能实现浅拷贝
compare(s1, s2)python
(1, 2, 3, [1, 2]) == (1, 2, 3, [1, 2]):True
(1, 2, 3, [1, 2]) is (1, 2, 3, [1, 2]):True
import copy
t1 = (1, 2, 3)
t2 = copy.deepcopy(t1) # 只包含不可变对象的元组不能实现深拷贝
compare(t1, t2)
(1, 2, 3) == (1, 2, 3):True
(1, 2, 3) is (1, 2, 3):True
import copy
s1 = (1, 2, 3,[1,2])
s2 = copy.deepcopy(s1) # 对一个包含可变对象的元组可以实现深度拷贝
compare(s1, s2)
(1, 2, 3, [1, 2]) == (1, 2, 3, [1, 2]):True
(1, 2, 3, [1, 2]) is (1, 2, 3, [1, 2]):False
139823086708208 139823086707728
3.5.4 浅拷贝和深度拷贝的影响
# 浅拷贝:原对象的改变可能会影响新对象
import copy
l1 = [[1, 2], (30, 40)]
print(f"原对象:{l1}")
l2 = copy.copy(l1)
l1.append(100)
l1[0].append(3)
print(f"原对象修改:{l1}")
print(f"浅拷贝后的新对象:{l2}")
原对象:[[1, 2], (30, 40)]
原对象修改:[[1, 2, 3], (30, 40), 100]
浅拷贝后的新对象:[[1, 2, 3], (30, 40)]
# 深度拷贝:新对象和原对象没有任何关联
import copy
l1 = [[1, 2], (30, 40)]
print(f"原对象:{l1}")
l2 = copy.deepcopy(l1)
l1.append(100)
l1[0].append(3)
print(f"原对象修改:{l1}")
print(f"深度拷贝后的新对象:{l2}")
原对象:[[1, 2], (30, 40)]
原对象修改:[[1, 2, 3], (30, 40), 100]
深度拷贝后的新对象:[[1, 2], (30, 40)]
3.5.6 用一个深度拷贝,拷贝一个无限嵌套的列表,是否相等
import copy
x = [1]
x.append(x)
y = copy.deepcopy(x)
print(len(y)) # 输出为2
if x == y:
print(True)
else:
print(False)
# 运行报错:RecursionError: maximum recursion depth exceeded in comparison

总结

一、赋值:

在 Python 中,对象的赋值就是简单的对象引用,这点和 C++不同

二、浅拷贝(shallow copy):

浅拷贝会创建新对象,重新分配内存,其内容非原对象本身的引用,而是原对象内第一层对象的引用。浅拷贝有三种形式:切片操作工厂函数copy 模块中的 copy 函数

三、深拷贝(deep copy):

深拷贝只有一种形式,copy 模块中的 deepcopy()函数。深拷贝和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因此,它的时间和空间开销要高。

四、拷贝的注意点:

1、对于非容器类型,如数字、字符,以及其他的“原子”类型,没有拷贝一说,产生的都是原对象的引用

2、如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。

写在最后:

吐血整理,不过好在是终于理清了,文章中所有的例子可以在jupyter nootbook上运行,转载请注明出处,谢谢!!

Python比较操作符、变量赋值、对象拷贝的更多相关文章

  1. Python中的变量引用对象需注意的几点

    Python中的变量引用对象需注意的几点 分类:Python (55)  (0) 普通引用: Python中,变量的作用仅仅是一个标识,只有赋值后才被创建,它可以引用任何类型的对象,而且在引用之前必须 ...

  2. 第2章 Python编程基础知识 第2.1节 简单的Python数据类型、变量赋值及输入输出

    第三节 简单的Python数据类型.变量赋值及输入输出 Python是一门解释性语言,它的执行依赖于Python提供的执行环境,前面一章介绍了Python环境安装.WINDOWS系列Python编辑和 ...

  3. python中的变量与对象

    一. 什么是变量 变量就是以前学习的数学中常见的等式x = 3(x是变量,3是变量值),在编程中,变量不仅可以是数学,还可以是任意数据类型 二. 变量的命名规则 变量名必须是英文大小写.数字和_的组合 ...

  4. Python基础-注释-变量赋值

    一.注释 # 注释 \n 行分隔符 \ 继续上一行 '''   *** ''' 多行注释 二.基本规则 : 分开代码块(组)   头$尾 缩进块  语句代码块  用缩进深度区分 空行     用于分割 ...

  5. Python中的变量、对象

    由于没时间系统学习下Python 只能见一个问题探究一个问题了 一.初级 - 对象 关于Python中的数据类型,今天重新认识了下.[参考] 首先,Python中,对象才有类型, 变量是没有类型的,它 ...

  6. Python学习四|变量、对象、引用的介绍

    变量 变量创建:一个变量也就是变量名,就像a,当代码第一次赋值时就创建了它.之后的赋值将会改变已创建的变量名的值,从技术上讲,Python在代码运行之前先检测变量名,可以当成是最初的赋值创建了变量. ...

  7. 【python】字符串变量赋值时字符串可用单或双引号

    >>> name='萧峰' >>> print(name) 萧峰 >>> name="独孤求败" >>> p ...

  8. python多个变量赋值

    a, b = 3, 4 c, d = 3, 4 a, b = b, a + b c = d d = c + d print(a, b, c, d) 输出: 4 7 4 8 因为a, b和b, a + ...

  9. python中的变量和字符串

    一.变量 1.python变量 *变量用于存储某个或某些特定的值,它与一个特定标识符相关联,该标识符称为变量名称.变量名指向存储在内存中的值.在创建变量时会在内存中开辟一个空间.基于变量的数据类型,解 ...

随机推荐

  1. pytorch入门2.0构建回归模型初体验(数据生成)

    pytorch入门2.x构建回归模型系列: pytorch入门2.0构建回归模型初体验(数据生成) pytorch入门2.1构建回归模型初体验(模型构建) pytorch入门2.2构建回归模型初体验( ...

  2. 千万不要更新网易云音乐UWP!!!!!

    网易云音乐UWP没了!!! 现在 Micrsoft Store 里面的是垃圾 Win32 转置版!!!! 万不可更新!!! 若已经更新,还有救回来的办法:下载 https://lanzous.com/ ...

  3. CISCN 2019-ikun

    0x01 进去网址,页面如下: 刚开始有个登陆和注册的按钮,上图是我已经注册后登陆成功后的页面,我们发现在图的左下角给了一个关键的提示,购买LV6,通过寻找我们发现页面数很多,大概500页,一个一个找 ...

  4. 使用vuex中的store存储数据

    Vuex是一个专门为Vue.js应用程序开发的状态管理模式,这个状态自管理应用包括三个模式 state 驱动应用的数据源 view 以声明方式将state映射到视图 actions 响应在view上的 ...

  5. CODING DevOps 系列第四课:DevOps 中的质量内建实践

    什么是质量内建 随着时间的推移,我们项目的开发效率会逐渐降低,直到几年之后整个项目可能就无法维护,只能推倒重来.具体的表现首先就是随着时间推移,我们会发现整个需求列表里面能做的需求越来越少,因为每当我 ...

  6. 这一次搞懂Spring Web零xml配置原理以及父子容器关系

    前言 在使用Spring和SpringMVC的老版本进行开发时,我们需要配置很多的xml文件,非常的繁琐,总是让用户自行选择配置也是非常不好的.基于约定大于配置的规定,Spring提供了很多注解帮助我 ...

  7. 10.DRF-认证

    Django rest framework源码分析(1)----认证 一.基础 1.1.安装 两种方式: github pip直接安装 pip install djangorestframework ...

  8. JavaWeb网上图书商城完整项目--day02-15.登录功能流程分析

    当用户点击登录界面的登录按钮的时候,将登录的用户名.密码和验证码上传到后台,后台的业务流程如下面所示:

  9. mysql语句基本练习

    select ename,job from emp where job in ('MANAGER','ANALYET','SALESMAN') 1.查询出工作岗位为MANAGER.ANALYST.SA ...

  10. Spring Redis开启事务支持错误用法导致服务不可用

      1.事故背景 在APP访问服务器接口时需要从redis中获取token进行校验,服务器上线后发现一开始可以正常访问,但只要短时间内请求量增长服务则无法响应 2.排查流程 (1)使用top指令查看C ...