1.4-python基础-小数据池,代码块,深浅copy
小数据池,代码块,深浅copy
id,is, ==
id是内存地址,只要创建一个数据(对象)就会在内存中开辟一个空间,将这个数据临时加载到内存中,这个空间是有一个唯一标识的。标志这个空间的叫做内存地址,也就是这个数据(对象)的id。可以用id()获取数据的内存地址:
name = '黑色利穆'
print(id(name)) # 2186804190928
== 是比较两边数值是否相等,
is 是比较两边的内存地址是否相等,如果内存地址相等,两边就是指向同一个内存地址;
l1 = 1000
l2 = 1000
print(l1 is l2) # False
print(l1 == l2) # True
如果内存地址相等,值肯定形同。如果值相等,内存地址不一定相同;
代码块
python程序是由代码块构成的,块是一个python程序的文本,是作为一个单元执行的;
代码块:一个模块,一个函数,一个类,一个文件都是一个代码块;
作为交互方式输入的每个命令都是一个代码块;
对于一个文件中的两个函数,分别是两个不同的代码块;
def func():
pass # 一个代码块
def func1():
pass # 另一个代码块
代码块的缓存机制
前提条件:在同一个代码块内;
机制内容:python在执行同一个代码块的初始化对象的命令时,会检查是否其值已经存在,如果存在,会将其重用。举例:文件执行时(同一个代码块)会把l1,l2两个变量指向同一个对象,满足缓存机制则他们在内存中只存在一个,即:id相同。
适用对象:int(float),str,bool。
对象的具体细则:
int(float):任何数字在同一代码块下都会复用;
bool:True和False在字典中会以1,0方式存在,并且复用;
str:几乎所有的字符串都会符合缓存机制,具体如下:
1.非乘法得到的字符串都满足代码块的缓存机制;
2.乘法得到的字符串分两种情况;
2.1. 乘数为1时,任何字符串满足代码块的缓存机制;
2.2. 乘数>=2时,仅含大小写字母,数字,下划线,总长度<=20,满足代码块的缓存机制;
优点:能够提高一些字符串,整数处理在时间和空间上的性能;需要值相同的字符串,整数的时候,直接从‘字典’中取出复用,避免频繁的创建和销毁,提高效率,节约内存;
小数据池
前提条件:在不同的代码块内;
机制内容:
python自动将-5~256的整数进行了缓存,当将这些整数赋值给变量时,并不会重新创建对象,而是使用已经创建好的缓存对象;
python会将一定规则的字符串在字符串驻留池中创建一份,当将这些字符串赋值给变量时,并不会重新创建对象,而是使用在字符串驻留池中创建好的对象;
适用对象:int(float),str,bool;
对象的具体细则:
int:小数据池的范围是-5~256,如果多个变量都是指向同一个(这个范围内)的数字,他们在内存中都是一个内存地址;
a = 100
b = 100
c = 100
print(id(a), id(b), id(c))
# 2000189552 2000189552 2000189552
str:字符串:
1.字符串的长度为0或者1,默认都采用了驻留机制(小数据池)
a = '@'
b = '@'
print(a is b) # True
2.字符串的长度>1,且只含有大小写字母,数字,下划线,会默认驻留
a = 'hei_se_li_mu_666_888'
b = 'hei_se_li_mu_666_888'
print(a is b) # True
3.用乘法得到字符串,分两种情况:
3.1 乘数为1时:仅含大小写字母,数字,下划线,默认驻留
3.2 含其他字符,长度<=1 默认驻留
3.3 含其他字符,长度>1,默认驻留
3.4 乘数>=2时,仅含大小写字母,数字,下划线,总长度<=20,默认驻留
a = 'aaabbbccc_123123_AAAA'
b = a * 1
print(a is b) # True
a = '@'
b = a * 1
print(a is b) # True
a = '$#'
b = a * 1
print(a is b) # True
a = 'hslma' * 4
b = 'hslma' * 4
print(a is b) # True
指定驻留:
指定驻留就是可以指定任意的字符串加入到小数据池中,让其只在内存中创建一个对象,多个变量都指向这一个字符串;
from sys import intern
a = intern('hello!!!!!!!' * 20)
b = intern('hello!!!!!!!' * 20)
print(a is b) # True
bool值就是True,False,无论你创建多少个变量指向True,False,他在内存中只存在一个。
优点:能够提高一些字符串,整数处理人物在时间和空间上的性能;需要值相同的字符串,整数的时候,直接从'池'里拿来用,避免频繁的创建和销毁,提升效率,节约内存;
总结:
如果在同一代码块下,则采用同一代码块下的缓存机制;
如果是不同代码块,则采用小数据池的驻留机制;
pycharm通过运行文件的方式执行代码块,是在同一个文件下(同一个代码块下),采用同一代码块下的缓存机制;
通过交互方式执行,是不同代码块下,则采用小数据池的驻留机制;
虽然在同一个文件,但函数本身就是代码块,所以这是在两个不同的代码块下,不满足小数据池(驻留机制),则指向两个不同的地址;
深浅copy
copy就是复制一份,深浅copy就是完全复制一份,和部分复制一份的意思;
赋值运算:
l1 = [1, 2, 3, ['heise', 'limu']]
l2 = l1
l1[0] = 777
print(l1)
print(l2)
# [777, 2, 3, ['heise', 'limu']]
# [777, 2, 3, ['heise', 'limu']]
l1[3][0] = 'baise'
print(l1)
print(l2)
# [777, 2, 3, ['baise', 'limu']]
# [777, 2, 3, ['baise', 'limu']]
# 对于赋值运算来说,l1和l2指向的是同一个内存地址,所以是完全一样的。
浅拷贝copy
l1 = [1, 2, 3, True, (1, 2, 3), [11, 22]]
l2 = l1.copy()
print(id(l1), id(l2))
# 2677693097864 2677693910472
print(id(l1[-2]), id(l2[-2]))
# 2677693879064 2677693879064
print(id(l1[-1]), id(l2[-1]))
# 2677693097800 2677693097800
# 对于浅拷贝来说,只是在内存中重新开辟了一个空间存放一个新列表,但是新列表中的元素与原列表中的元素的公用的;
深拷贝deepcopy
import copy
l1 = [1, 'heise', True, (1, 2, 3), [11, 22]]
l2 = copy.deepcopy(l1)
print(id(l1), id(l2))
# 2224781980872 2224781982152
print(id(l1[-2]), id(l2[-2]))
# 2224781529880 2224781529880
print(id(l1[-1]), id(l2[-1]))
# 2224781980680 2224781982088
# 深copy的特性:将可变的数据类型在内存中重新创建一份,不可变数据类型沿用之前的;
l1 = [1,2,3,4,['heiselimu']]
l2 = l1[::]
l1[-1].append(777)
print(l2)
# [1, 2, 3, 4, ['heiselimu', 777]]