Python高级语法1:GIL锁&浅拷贝&深拷贝

简介: Python高级语法1:GIL锁&浅拷贝&深拷贝

一、GIL锁


  • 1.1、GIL面试题:描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因。
  • Guido的声明: he language doesn't require the GIL -- it's only the CPython virtual machine that has historically been unable to shed it.


  • 1.2、参考答案:


  • (1)、Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在Cpython虚拟机(解释器),难以移除GIL。
  • (2)、GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。
  • (3)、线程释放GIL锁的情况: 在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100
  • (4)、Python使用多进程是可以利用多核的CPU资源的。
  • (5)、多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁


二、浅拷贝


  • 2.1、浅拷贝是对于一个对象的顶层拷贝,简单的理解是:拷贝了引用,并没有拷贝内容
  • 2.2、 看一个最简单的浅拷贝


image.png


  • 以上:a 与 b 的内存地址相同,说明了当给一个变量赋值的时候,其实就是将数据的引用赋值了一份给另外一个变量,这其实就是最简单的浅拷贝,不仅列表是这样,只要是 类似于 xx1 = xx2 的这种基本都是 浅拷贝,如下:


>>> c = {"age":23}
>>> d = c
>>> id(c)
4527333240
>>> id(d)
4527333240
>>> c["name"] = "王小二"
>>> c
{'age': 23, 'name': '王小二'}
>>> d
{'age': 23, 'name': '王小二'}
  • 因为都是浅拷贝,所以只要通过一个引用进行了修改,那么另外一个变量就看到的数 据也就变化了


  • 2.3、import copy 模块中 copy.copy() 的使用


>>> a = [11,22]
>>> b = [33,44]
>>> c = [a,b]
>>> id(a)
4528760776
>>> id(b)
4528427464
>>> id(c)
4528012488
>>> import copy
>>> d = copy.copy(c)
>>> id(d)
4528788488
>>> id(d[0])
4528760776
>>> id(d[1])
4528427464
>>> a.append(55)
>>> c
[[11, 22, 55], [33, 44]]
>>> d
[[11, 22, 55], [33, 44]]


image.png


浅拷贝 只会复制最顶层的那个列表


三、深拷贝



  • 3.1、深拷贝是对于一个对象所有层次的拷贝(递归)


>>> a = [11,22]
>>> b = copy.deepcopy(a)
>>> a
[11, 22]
>>> b
[11, 22]
>>> id(a)
4528761928
>>> id(b)
4528933000
  • 以上结果通过deepcopy()确实将列表 a 中所有的数据的引用  copy 了,而不是只拷贝了 a 指向的列表的引用,看如下,a的数据发生变化的时候,b并不会发生变化


>>> a.append(55)
>>> a
[11, 22, 55]
>>> b
[11, 22]


3.2、进一步理解 深拷贝

image.png


  • 深拷贝:  我个人理解其实是:深拷贝后与原来的对象没有任何关系了,不管原来的对象如何变化,都不再会影响到深拷贝后的对象


四、拷贝的其他方式



  • 4.1、分片表达式 可以赋值一个序列


>>> a = [11,22]
>>> b = [33,44]
>>> c = [a,b]
>>> d = c[:]
>>> id(c)
4528760776
>>> id(d)
4528932936
>>> id(c[0])
4528933000
>>> id(d[0])
4528933000
>>> a
[11, 22]
>>> a.append(55)
>>> c
[[11, 22, 55], [33, 44]]
>>> d
[[11, 22, 55], [33, 44]]



image.png



d=c[:]d=copy.copy(c) 一样 属于 浅拷贝


  • 4.2、字典的copy方法可以拷贝一个字典


image.png


五、注意点



  • 5.1、浅拷贝对不可变类型和可变类型的copy不同
  • copy.copy 对于 可变类型,会进行浅拷贝


>>> a = [11,22]
>>> b = copy.copy(a)
>>> id(a)
4528932552
>>> id(b)
4528932680
>>> a.append(33)
>>> a
[11, 22, 33]
>>> b
[11, 22]
  • 解释一下大家的对于a变化,而b不变化的问题,因为b拷贝的是a里面 11,22引用的指向,当a添加 33的时候,而 11,22引用的指向并没有发生变化,所以并不会发生变化


  • copy.copy 对于 不可变类型,不会拷贝,仅仅是指向


>>> a = (11,22,33)
>>> b = copy.copy(a)
>>> id(a)
4528768632
>>> id(b)
4528768632
  • 如果c是元组,那么copy时会,仅仅是元组的引用copy,而 deepcopy依然是深copy,即递归copy所有


>>> a = [11,22]
>>> b = [33,44]
>>> c = (a,b)
>>> d = copy.copy(c)
>>> id(c)
4528885256
>>> id(d)
4528885256
>>> a.append(55)
>>> c
([11, 22, 55], [33, 44])
>>> d
([11, 22, 55], [33, 44])
>>> e = copy.deepcopy(c)
>>> id(c)
4528885256
>>> id(e)
4528885448
>>> a.append(66)
>>> c
([11, 22, 55, 66], [33, 44])
>>> e
([11, 22, 55], [33, 44])
>>>
  • 5.2、copy.copy和copy.deepcopy的区别
  • copy.copy


>>> a = [11,22]
>>> b = (a,)
>>> c = [b,]
>>> 
>>> d = copy.copy(c)
>>> 
>>> c
[([11, 22],)]
>>> d
[([11, 22],)]
>>> a.append(33)
>>> c
[([11, 22, 33],)]
>>> d
[([11, 22, 33],)]
>>> id(c)
4528932936
>>> id(d)
4528012488
>>> id(c[0])
4528434200
>>> id(d[0])
4528434200


image.png



d = c # 让d这个变量指向c指向的空间,d = copy.copy(c) # 复制所有c指向的数据到一个新的空间,但是不会递归copy


  • copy.deepcopy


>>> a = [11,22]
>>> b = (a,)
>>> c = [b]
>>> 
>>> d = copy.deepcopy(c)
>>> 
>>> c
[([11, 22],)]
>>> d
[([11, 22],)]
>>> 
>>> id(c)
4528932680
>>> id(d)
4528761928
>>> 
>>> id(c[0])
4528913040
>>> id(d[0])
4528913096
>>> 
>>> a.append(33)
>>> 
>>> c
[([11, 22, 33],)]
>>> d
[([11, 22],)]
>>>


image.png


image.png

目录
相关文章
|
3月前
|
人工智能 Ubuntu IDE
【Python】基础:环境配置与基础语法
本文介绍了Python编程语言及其环境配置方法。Python由Guido van Rossum于1991年创建,以其简洁、易学和强大的功能著称。文章详细讲解了Python的主要特点、Windows和Ubuntu下的安装配置步骤、基础语法、控制流、函数、文件操作、模块使用及面向对象编程等内容,帮助读者快速入门Python编程。
89 4
|
2月前
|
IDE 数据挖掘 开发工具
Python作为一种广受欢迎的高级编程语言,以其简洁的语法和强大的功能吸引了众多初学者和专业开发者
Python作为一种广受欢迎的高级编程语言,以其简洁的语法和强大的功能吸引了众多初学者和专业开发者
40 7
|
2月前
|
存储 索引 Python
Python 的基本语法
这些是 Python 的基本语法要素,掌握它们是学习和使用 Python 的基础。通过不断地实践和应用,你将能够更深入地理解和熟练运用这些语法知识,从而编写出高效、简洁的 Python 代码
79 5
|
2月前
|
存储 Python
Python编程入门:理解基础语法与编写简单程序
本文旨在为初学者提供一个关于如何开始使用Python编程语言的指南。我们将从安装Python环境开始,逐步介绍变量、数据类型、控制结构、函数和模块等基本概念。通过实例演示和练习,读者将学会如何编写简单的Python程序,并了解如何解决常见的编程问题。文章最后将提供一些资源,以供进一步学习和实践。
45 1
|
2月前
|
机器学习/深度学习 数据挖掘 开发者
Python编程入门:理解基础语法与编写第一个程序
【10月更文挑战第37天】本文旨在为初学者提供Python编程的初步了解,通过简明的语言和直观的例子,引导读者掌握Python的基础语法,并完成一个简单的程序。我们将从变量、数据类型到控制结构,逐步展开讲解,确保即使是编程新手也能轻松跟上。文章末尾附有完整代码示例,供读者参考和实践。
|
2月前
|
存储 Python Perl
python正则语法
本文介绍了正则表达式的基础知识及其在 Python 中的应用。首先解释了为什么要使用正则表达式,通过一个判断手机号的示例展示了正则表达式的简洁性。接着详细介绍了 `re` 模块的常用方法,如 `match()`、`search()`、`findall()`、`finditer()` 等,并讲解了正则表达式的基本语法,包括匹配单个字符、数字、锚字符和限定符等。最后,文章还探讨了正则表达式的高级特性,如分组、编译和贪婪与非贪婪模式。
26 2
|
3月前
|
存储 程序员 开发者
Python编程入门:从零开始掌握基础语法
【10月更文挑战第21天】本文将带你走进Python的世界,通过浅显易懂的语言和实例,让你快速了解并掌握Python的基础语法。无论你是编程新手还是想学习一门新的编程语言,这篇文章都将是你的不二之选。我们将一起探索变量、数据类型、运算符、控制结构、函数等基本概念,并通过实际代码示例加深理解。准备好了吗?让我们开始吧!
|
3月前
|
存储 C语言 索引
Python 语法及入门 (超全超详细) 专为Python零基础 一篇博客让你完全掌握Python语法
本文全面介绍了Python的基础知识,包括Python的诞生背景、为什么学习Python、Python的应用场景、Python环境的安装、Python的基础语法、数据类型、控制流、函数以及数据容器的使用方法,旨在为Python零基础读者提供一篇全面掌握Python语法的博客。
153 0
Python 语法及入门 (超全超详细) 专为Python零基础 一篇博客让你完全掌握Python语法
|
3月前
|
存储 数据可视化 数据处理
【Python篇】快速理解Python语法:全面指南
【Python篇】快速理解Python语法:全面指南
65 1
|
4月前
|
Java Linux C++
30天拿下Python之基础语法
30天拿下Python之基础语法
38 4