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]]
posted @ 2020-12-03 18:39  黑色利穆  阅读(68)  评论(0编辑  收藏  举报