一、代码块及其缓存机制

代码块

一个模块、一个函数、一个类、一个文件等都是一个代码块;交互式命令下,一行就是一个代码块。

同一个代码块内的缓存机制(字符串驻留机制)

机制内容:Python在执行同一个代码块的初始化对象的命令时,会检查是否其值是否已经存在,如果存在,会将其重用,即将两个变量指向同一个对象。换句话说:执行同一个代码块时,遇到初始化对象的命令时,他会将初始化的这个变量与值存储在一个字典中,在遇到新的变量时,会先在字典中查询记录,如果有同样的记录那么它会重复使用这个字典中的之前的这个值。所以在你给出的例子中,文件执行时(同一个代码块)会把i1、i2两个变量指向同一个对象,满足缓存机制则他们在内存中只存在一个,即:id相同。

适用对象: int(float),str,bool。

对象的具体细则:(了解)

  • int(float):任何数字在同一代码块下都会复用。

  • bool:True和False在字典中会以1,0方式存在,并且复用。

  • str:几乎所有的字符串都会符合字符串驻留机制

不同代码块间的缓存机制(小数据池、小整数缓存机制、小整数驻留机制)

适用对象: int(float),str,bool

具体细则:-5~256数字,bool,满足一定规则的字符串

优点:提升性能,节省内存。

Python自动将-5~256的整数进行了缓存,当你将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象。

python会将一定规则的字符串在字符串驻留池中,创建一份,当你将这些字符串赋值给变量时,并不会重新创建对象, 而是使用在字符串驻留池中创建好的对象。

其实,无论是缓存还是字符串驻留池,都是python做的一个优化,就是将~5-256的整数,和一定规则的字符串,放在一个‘池’(容器,或者字典)中,无论程序中那些变量指向这些范围内的整数或者字符串,那么他直接在这个‘池’中引用,言外之意,就是内存中之创建一个。

#同一个代码块内的缓存机制————任何数字在同一代码块下都会复用i1 = 1000i2 = 1000print(id(i1))print(id(i2))​输出结果:3210011232100112
#同一个代码块内的缓存机制————几乎所有的字符串都会符合缓存机制s1 = 'hfdjka6757fdslslgaj@!#fkdjlsafjdskl;fjds中国's2 = 'hfdjka6757fdslslgaj@!#fkdjlsafjdskl;fjds中国'print(id(s1))print(id(s2))​输出结果:3161667231616672
#同一个代码块内的缓存机制————非数字、str、bool类型数据,指向的内存地址一定不同t1 = (1,2,3)t2 = (1,2,3)l1 = [1,2,3]l2 = [1,2,3]print(id(t1))print(id(t2))print(id(l1))print(id(l2))​输出结果:32191328321914723221069632232712

二、深浅copy

赋值运算讨论

令y=x,然后对x重新赋值时:

  • 若x, y为不可变数据类型(可哈西的数据类型)(int, str, bool, tuple),则y不会跟着x的变化而变化

  • 若x, y为可变数据类型(不可哈西的数据类型)(list, dict, set),则y会跟着x的变化而变化

#int的例子
x=1
y=x
x=x+1
print(x)
print(y)

输出结果:
2
1
#str的例子
x='abc'
y=x
x=x+'d'
print(x)
print(y)

输出结果:
abcd
abc
#bool的例子
x=True
y=x
x=False
print(x)
print(y)

输出结果:
False
True
#tuple的例子
x=(1,2)
y=x
x=(3,4)
print(x)
print(y)

输出结果:
(3, 4)
(1, 2)
#list的例子
x=[1,2]
y=x
x.append(3)
print(x)
print(y)

输出结果:
[1, 2, 3]
[1, 2, 3]
#dict的例子
x={1:2,3:4}
y=x
x[5]=6
print(x)
print(y)

输出结果:
{1: 2, 3: 4, 5: 6}
{1: 2, 3: 4, 5: 6}
#set的例子
x={1,2}
y=x
x.add(3)
print(x)
print(y)

输出结果:
{1, 2, 3}
{1, 2, 3}

不可变数据类型(可哈西的数据类型)(int, str, bool, tuple)原理图:

可变数据类型(不可哈西的数据类型)(list, dict, set)原理图:

浅copy

拷贝目标可变对象(list, dict, set)时,仅为第一层可变对象分配新的内存地址,第二层及以上的可变对象沿用之前对象的内存地址,此外所有层的不可变对象(int, str, bool, tuple)均沿用之前对象的内存地址。

#更改第一层的例子
l1 = [1, 2, 3, [22, 33]]
l2 = l1.copy()
l1.append(666)
print(l1,id(l1))
print(l2,id(l2))
print(l1[0],id(l1[0]))
print(l2[0],id(l2[0]))
print(l1[3],id(l1[3]))
print(l2[3],id(l2[3]))

输出结果:
[1, 2, 3, [22, 33], 666] 43242760
[1, 2, 3, [22, 33]] 43243208
1 1414365296
1 1414365296
[22, 33] 43220744
[22, 33] 43220744
#更改第二层的例子
l1 = [1, 2, 3, [22, 33]]
l2 = l1.copy()
l1[-1].append(666)
print(l1, id(l1))
print(l2, id(l2))
print(l1[0],id(l1[0]))
print(l1[0],id(l2[0]))
print(l1[-1],id(l1[-1]))
print(l1[-1],id(l2[-1]))

输出结果:
[1, 2, 3, [22, 33, 666]] 43046152
[1, 2, 3, [22, 33, 666]] 43046600
1 1414365296
1 1414365296
[22, 33, 666] 43024136
[22, 33, 666] 43024136

浅copy的另一种表示方式(此种方式必须在前面写import copy搭建模块,否则报错!)

import copy
x=[1,2,3]
y=copy.copy(x)

深copy

拷贝目标可变对象(list, dict, set)时,为所有层的可变对象分配新的内存地址,此外所有层的不可变对象(int, str, bool, tuple)均沿用之前对象的内存地址。

必须在前面写import copy搭建模块,否则报错!

import copy
l1 = [1, 2, 3, [22, 33]]
l2 = copy.deepcopy(l1)
print(l1,id(l1))
print(l2,id(l2))
print(l1[0],id(l1[0]))
print(l1[0],id(l2[0]))
print(l1[-1],id(l1[-1]))
print(l1[-1],id(l2[-1]))

输出结果:
[1, 2, 3, [22, 33]] 43650504
[1, 2, 3, [22, 33]] 43754248
1 1414365296
1 1414365296
[22, 33] 43650312
[22, 33] 43754184

Python中的代码块及其缓存机制、深浅copy的更多相关文章

  1. is, ==, id 用法、代码块和缓存机制

    id(): 获取对象的内存地址:print(id(i)) == : 比较两边的值是否相同 is : 判断内存地址是否相同 id相同,值一定相同 值相同,id不一定相同 代码块: Python是由代码块 ...

  2. day-06-集合-缓存机制-深浅copy

    (1) is id ==用法 is 判断的是内存地址是否相同 id 查看内存地址:id相同,值一定相同,值相同,id不一定相同 == 比较判断是否相等 l1 = [1, 2, 3] l2 = [1, ...

  3. 10 Python中的代码缓存机制

    目录: 1) 什么是代码块 2) 基本原理 3) 机制适用范围 4) 适用对象 5) 优势 更详细说明,参考太白老师博客 https://www.cnblogs.com/jin-xin/article ...

  4. Python 入门之代码块、小数据池 与 深浅拷贝

    Python 入门之代码块.小数据池 与 深浅拷贝 1.代码块 (1)一个py文件,一个函数,一个模块,终端中的每一行都是代码块 (代码块是防止我们频繁的开空间降低效率设计的,当我们定一个变量需要开辟 ...

  5. 用Python高亮org-mode代码块

    文章同时可在我的github blog上阅读:http://cheukyin.github.io/python/2014-08/pygments-highlight-src-export-html.h ...

  6. WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制

    原文:WCF技术剖析之八:ClientBase<T>中对ChannelFactory<T>的缓存机制 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service ...

  7. 关于RecyclerView中Viewholder和View的缓存机制的探究

    关于RecyclerView中Viewholder和View的缓存机制的探究 http://www.cnblogs.com/littlepanpc/p/4241575.html

  8. java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数

    一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构

  9. 【Java基础】2、Java中普通代码块,构造代码块,静态代码块区别及代码示例

    Java中普通代码块,构造代码块,静态代码块区别及代码示例.Java中普通代码块,构造代码块,静态代码块区别及代码示例 执行顺序:静态代码块>静态方法(main方法)>构造代码块>构 ...

随机推荐

  1. 5G手机来了,但这些问题让其短期内难以成为“香饽饽”

    在5G手机喊了太长时间后,其终于在近日不断亮相. 此前据中国质量认证中心官网显示,共有8款5G手机获得3C认证--华为4款,一加.中兴.OPPO和vivo各有一款.随着首批5G手机通过3C认证,意味着 ...

  2. TP5.1 分页(带参数传递)

    不带参数: $rs = Db::name('admin')->order(['id'=>'desc'])->paginate(1); 带参数传递: $rs=Db::name('adm ...

  3. jmeter的使用---录制脚本

    1.设置fidder 2.在fidder中导出请求,选择jmx格式

  4. C/S编程

    https://blog.csdn.net/antony1776/article/details/73717666 实现C/S程序,加上登录注册聊天等功能. 然后要做个协议的样子出来. 比如说注册功能 ...

  5. mybatis--MyBatis动态SQL语句

    mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类: 1. if 语句 (简单的条件判断) 2. ...

  6. MySQL 学习(三)事务学习

    事务隔离级别     SQL标准的事务隔离级别包括:读未提交(read uncommitted).读提交(read committed).可重复读(repeatable read)和串行化(seria ...

  7. 生成SSH密钥过程

    1.查看是否已经有了ssh密钥:cd ~/.ssh 如果没有密钥则不会有此文件夹,有则备份删除 2.生存密钥: $ ssh-keygen -t rsa -C "name@doumi.com& ...

  8. red hat 报错:apt-get:找不到命令

    Linux有两个系列:一个是RedHat系列,一个是Debian系列. RedHat系列:Redhat.Centos.Fedora等 Debian系列:Debian.Ubuntu等 RedHat 系列 ...

  9. WPscan扫描工具安装使用

    WPScan是Kali Linux默认自带的一款漏洞扫描工具,它采用Ruby编写,能够扫描WordPress网站中的多种安全漏洞,其中包括WordPress本身的漏洞.插件漏洞和主题漏洞.最新版本WP ...

  10. 6_3 矩阵链乘(UVa424)<用栈实现简单的表达式解析>

    假设你必须做A*B*C*D*E的运算,在这里A,B,C,D,E都是矩阵(matrix).由于矩阵相乘具有连接性(associative),所以相乘的顺序可以是任意的.然而所需要的基本乘法数却与不尽相同 ...