Python基础——深浅拷贝、python内存泄露、你并不了解的format、decimal
文章目录
深浅拷贝
先问问大家,什么是拷贝?拷贝是音译的词,其实他是从copy这个英文单词音译过来的,那什么是copy? copy其实就是复制一份,也就是所谓的抄一份。深浅copy其实就是完全复制一份,和部分复制一份的意思。
先看赋值运算
l1 = [1,2,3,['jason','egon']]
l2 = l1
l1[0] = 111
print(l1) # [111, 2, 3, ['jason', 'egon']]
print(l2) # [111, 2, 3, ['jason', 'egon']]
l1[3][0] = 'kevin'
print(l1) # [111, 2, 3, ['kevin', 'egon']]
print(l2) # [111, 2, 3, ['kevin', 'egon']]
对于赋值运算来说,l1与l2指向的是同一个内存地址,所以他们是完全一样的,在举个例子,比如张三李四合租在一起,那么对于客厅来说,他们是公用的,张三可以用,李四也可以用,但是突然有一天张三把客厅的的电视换成投影了,那么李四使用客厅时,想看电视没有了,而是投影了,对吧?l1,l2指向的是同一个列表,任何一个变量对列表进行改变,剩下那个变量在使用列表之后,这个列表就是发生改变之后的列表
浅拷贝copy
#同一代码块下:
l1 = [1, 'jason', True, (1,2,3), [22, 33]]
l2 = l1.copy()
print(id(l1), id(l2)) # 2713214468360 2713214524680
print(id(l1[-2]), id(l2[-2])) # 2547618888008 2547618888008
print(id(l1[-1]),id(l2[-1])) # 2547620322952 2547620322952
# 不同代码块下:
>>> l1 = [1, 'jason', True, (1, 2, 3), [22, 33]]
>>> l2 = l1.copy()
>>> print(id(l1), id(l2))
1477183162696
>>> print(id(l1[-2]), id(l2[-2]))
1477181814032
>>> print(id(l1[-1]), id(l2[-1]))
1477183162504
对于浅copy来说,只是在内存中重新创建了开辟了一个空间存放一个新列表,但是新列表中的元素与原列表中的元素是公用的

深拷贝deepcopy
# 同一代码块下
import copy
l1 = [1, 'jason', True, (1,2,3), [22, 33]]
l2 = copy.deepcopy(l1)
print(id(l1), id(l2)) # 2788324482440 2788324483016
print(id(l1[0]),id(l2[0])) # 1470562768 1470562768
print(id(l1[-1]),id(l2[-1])) # 2788324482632 2788324482696
print(id(l1[-2]),id(l2[-2])) # 2788323047752 2788323047752
# 不同代码块下
>>> import copy
>>> l1 = [1, 'jason', True, (1, 2, 3), [22, 33]]
>>> l2 = copy.deepcopy(l1)
>>> print(id(l1), id(l2))
1477183162632
>>> print(id(0), id(0))
1470562736
>>> print(id(-2), id(-2))
1470562672
>>> print(id(l1[-1]), id(l2[-1]))
1477183162312

对于深copy来说,列表是在内存中重新创建的,列表中可变的数据类型是重新创建的,列表中的不可变的数据类型是公用的
相关面试题
l1 = [1, 2, 3, 4, ['jason']]
l2 = l1[::]
l1[-1].append(666)
print(l2)
python内存泄露
起因
内存泄露指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。导致程序运行速度减慢甚至系统崩溃等严重后果。有 del() 函数的对象间的循环引用是导致内存泄漏的主凶

方案
不使用一个对象时使用:delobject 来删除一个对象的引用计数就可以有效防止内存泄漏问题。通过Python 扩展模块 gc 来查看不能回收的对象的详细信息。可以通过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为 0 来判断是否内存泄漏。
但是由于gc垃圾收集机制,要遍历所有被垃圾收集器管理的python对象(包括垃圾和非垃圾对象),该过程比较耗时可能会造成程序卡顿,会对某些对内存、cpu要求较高的场景造成性能影响。那怎么才能优雅地避免内存泄露呢?

编写安全的代码
比如对于下面发生内存泄露的cycle_ref函数,在函数结束前解除循环引用,即可解决内存泄露问题。
def cycle_ref():
a1 = A()
a2 = A()
a1.child = a2
a2.child = a1
# 解除循环引用,避免内存泄露
a1.child = None
a2.child = None
但是对于上述方法,我们有可能会忘记那一两行无关紧要的代码而造成灾难性后果,毕竟老虎也有打盹的时候。那怎么办?不要着急,Python已经为我们考虑到这点:弱引用。
弱引用
Python标准库提供了weakref模块,弱引用不会在引用计数中计数,其主要目的是解决循环引用。并非所有的对象都支持weakref,例如list和dict就不支持。下面是weakref比较常用的方法:
"""
1. class weakref.ref(object[, callback]) :创建一个弱引用对象,object是被引用的对象,callback是回调函数(当被引用对象被删除时,调用该回调函数)
2.weakref.proxy(object[, callback]):创建一个用弱引用实现的代理对象,参数同上
3.weakref.getweakrefcount(object) :获取对象object关联的弱引用对象数
4.weakref.getweakrefs(object):获取object关联的弱引用对象列表
5.class weakref.WeakKeyDictionary([dict]):创建key为弱引用对象的字典
6.class weakref.WeakValueDictionary([dict]):创建value为弱引用对象的字典
7.class weakref.WeakSet([elements]):创建成员为弱引用对象的集合对象
"""
同样对于上面发生内存泄露的cycle_ref函数,使用weakref稍加改造,便可更安全地解决内存泄露问题:
import weakref
class A(object):
def __init__(self):
self.data = [x for x in range(100000)]
self.child = None
def __del__(self):
pass
def cycle_ref():
a1 = A()
a2 = A()
a1.child = weakref.proxy(a2)
a2.child = weakref.proxy(a1)
if __name__ == '__main__':
import time
while True:
time.sleep(0.5)
cycle_ref()
你并不了解的format、decimal
谈到format的用法,大家肯定会说不就是用来处理字符串拼接的嘛,谈到decimal你能说出这句话我只能说小伙子你还太嫩了呦~~~让我来装个X天秀一波
format格式化数字



decimal精确处理数字

Python基础——深浅拷贝、python内存泄露、你并不了解的format、decimal的更多相关文章
- python基础--深浅拷贝copy
拷贝是音译的词,其实他是从copy这个英文单词音译过来的,那什么是copy? copy其实就是复制一份,也就是所谓的抄一份.深浅copy其实就是完全复制一份,和部分复制一份的意思. 1.赋值运算 l1 ...
- python基础-深浅拷贝
深拷贝与浅拷贝 总结: # 浅拷贝:list dict: 嵌套的可变数据类型是同一个 # 深拷贝:list dict: 嵌套的不可变数据类型彼此独立 浅拷贝 # 个人理解: # 在内存中重新创建一个空 ...
- Python原理 -- 深浅拷贝
python原理 -- 深浅拷贝 从数据类型说开去 str, num : 一次性创建, 不能被修改, 修改即是再创建. list,tuple,dict,set : 链表,当前元素记录, 下一个元素的位 ...
- Python的深浅拷贝
Python的深浅拷贝 深浅拷贝 1. 赋值,对于list, set, dict来说, 直接赋值. 其实是把内存地址交给变量并不是复制一份内容 list1 = [']] list2 = list1 p ...
- 深入理解 Python 的对象拷贝和内存布局
深入理解 Python 的对象拷贝和内存布局 前言 在本篇文章当中主要给大家介绍 python 当中的拷贝问题,话不多说我们直接看代码,你知道下面一些程序片段的输出结果吗? a = [1, 2, 3, ...
- python基础系列教程——Python中的编码问题,中文乱码问题
python基础系列教程——Python中的编码问题,中文乱码问题 如果不声明编码,则中文会报错,即使是注释也会报错. # -*- coding: UTF-8 -*- 或者 #coding=utf-8 ...
- python基础系列教程——Python库的安装与卸载
python基础系列教程——Python库的安装与卸载 2.1 Python库的安装 window下python2.python3安装包的方法 2.1.1在线安装 安装好python.设置好环境变量后 ...
- python基础系列教程——Python的安装与测试:python的IDE工具PyDev和pycharm,anaconda
---恢复内容开始--- python基础系列教程——Python的安装与测试:python的IDE工具PyDev和pycharm,anaconda 从头开启python的开发环境搭建.安装比较简单, ...
- 深浅拷贝 python
原文:http://www.jb51.net/article/15714.htm 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象.2. copy.deepcopy 深拷贝 ...
- Python入门-深浅拷贝
首先我们在这里先补充一下基础数据类型的一些知识: 一.循环删除 1.前面我们学了列表,字典和集合的一些操作方法:增删改查,现在我们来看一下这个问题: 有这样一个列表: lst = ['周杰伦','周润 ...
随机推荐
- 【技术积累】Java中的集合框架【一】
什么是Java集合框架? Java集合框架是Java编程语言中提供的一组接口.实现和算法,用于存储和操作数据集合.集合框架可以让程序员更加高效地组织和操作数据,而无需手动实现底层数据结构. Java集 ...
- 如何扩展及优化CI/CD流水线?
如今应用程序的开发通常由多个开发人员组成的团队完成.每个人或团队在项目中发挥自己的作用,然后我们发现在项目的末尾总是有几段代码需要编译,根据每个人的工作方法,管理这种集成可能会浪费很多时间.持续集成和 ...
- Apache Hudi 元数据字段揭秘
介绍 Apache Hudi 最初由Uber于 2016 年开发,旨在实现一个交易型数据湖,该数据湖可以快速可靠地支持更新,以支持公司拼车平台的大规模增长. Apache Hudi 现在被业内许多人广 ...
- Hexo博客Next主题添加粒子时钟特效
博客应用canvas粒子时钟的操作步骤: 在\themes\next\layout\_custom\目录下,新建clock.swig文件,内容如下: <div style="" ...
- 【调制解调】PM 调相
说明 学习数字信号处理算法时整理的学习笔记.同系列文章目录可见 <DSP 学习之路>目录,代码已上传到 Github - ModulationAndDemodulation.本篇介绍 PM ...
- C语言基础-结构体基础
文章目录 前言 1.结构体的创建 1.1 第一种方法 1.2 第二种方法 1.3 全局结构体和局部结构体的声明 2.结构体的使用 2.1 局部结构体的声明 & 初始化 2.1.1 指针方法 2 ...
- OO第一次大作业
前言 前言的前言 这是我的第一篇blog,有点小激动,我还找教程设置了一下我的背景,本来还想弄个页面小宠物,但是看了一下感觉有点复杂,下次一定.如果对我blog的内容有任何修正或者建议可以评论让我知道 ...
- Llama 2 来袭 - 在 Hugging Face 上玩转它
引言 今天,Meta 发布了 Llama 2,其包含了一系列最先进的开放大语言模型,我们很高兴能够将其全面集成入 Hugging Face,并全力支持其发布. Llama 2 的社区许可证相当宽松,且 ...
- 面试题 01.03. URL化
面试题 01.03. URL化 简单 URL化.编写一种方法,将字符串中的空格全部替换为%20.假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的"真实"长度.(注:用Ja ...
- 零基础入门——从零开始学习PHP反序列化笔记(二)
魔术方法 魔术方法介绍 __construct() 触发时机:实例化对象之前 构造函数,在实例化一个对象的时候,首先会去自动执行的一个方法; <?php class User { public ...