python基础 day6 id和is、代码块、集合、深浅拷贝

一、id is ==

# id
# s = 'Jason'
# print(id(s))  # id的值是随机的
#
# l1 = [1, 2, 3]
# l2 = [1, 2, 3]
# print(l1 == l2)  # 结果为True,== 比较的是两边的值是否相等

# is 判断的是内存地址是否相同
l1 = [1, 2, 3]
l2 = [1, 2, 3]
print(l1 is l2)  # 结果为false,因为l1和l2分别创建了两个内存地址

s1 = 'Jason'
s2 = 'Jason'
print(s1 is s2)  # 结果为True,因为字符串只占一个内存地址

"""
id相同,值肯定相同;
值相同,id不一定相同
"""

二、代码块

Python程序是由代码块构造的。块是一个python程序的文本,它是作为一个单元执行的。
代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块。
作为交互方式(cmd进入python解释器)输入的每个命令都是一个代码块。

两个机制:同一个代码块下,有一个机制;不同代码块下,遵循另一个机制。

1. 同一个代码块下的缓存机制:

​ 在同一个代码块下遇到初始化对象的命令时,会将初始化的变量和值放在一个字典中,在遇到新的变量时,先到字典中去查找有没有相同的值,如果有,则重复使用该值。

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

  • 适用对象

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

    i1 = 1
    i2 = 1
    i3 = 1
    print(i1 is i2 is i3)
    # 结果为True
    

    str:

    1. 非乘法得到的字符串都满足代码块的缓存机制:
    s1 = '三上悠亚 aloha\t!@#*('
    s2 = '三上悠亚 aloha\t!@#*('
    s3 = '三上悠亚 aloha\t!@#*('
    print(s1 is s2 is s3)
    # 结果为True
    
    1. 乘数为1时,任何字符串满足代码块的缓存机制:
    s1 = '三上悠亚 aloha\t!@#*(' * 1
    s2 = '三上悠亚 aloha\t!@#*(' * 1
    s3 = '三上悠亚 aloha\t!@#*(' * 1
    print(s1 is s2 is s3)
    # 结果为True
    
    1. 乘数>=2时:字符串仅包含大小写字母,数字,下划线,相乘之后总长度<=20,满足代码块的缓存机制:
    s1 = '三上悠亚 aloha\t!@#*(' * 2
    s2 = '三上悠亚 aloha\t!@#*(' * 2
    s3 = '三上悠亚 aloha\t!@#*(' * 2
    print(s1 is s2 is s3)
    # 结果为False
    
    s1 = 'Aloha_' * 3
    s2 = 'Aloha_' * 3
    s3 = 'Aloha_' * 3
    print(s1 is s2 is s3)
    # 结果为True
    

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

2. 不同代码块下的缓存机制:小数据池

在不同代码块下 数字-5~256 和一定规则的字符串可以复用。
优点:提升性能,节省内存

三、集合(set)

  • 集合是一种可迭代的、无序的、不能包含重复元素的数据结构

  • 集合是一种容器型数据类型

  • 集合中的元素都是不可变的(可哈希)元素,而集合本身是可变的数据类型。

    即集合中不能有列表(list)、字典(dict)、集合(set),可以放数字(int)、字符串(str)、布尔值(bool)

  • 集合的作用:1.列表去重

    ​ 2.关系测试:交集、并集、差集

  1. 利用集合的特性给列表去重, 但是不能保持原来的顺序
list1 = [1, 2, 2, 2, 2, 3, 3, 3, 'jason', 'jason']
set1 = set(list1)
list1 = list(set1)
print(list1)
  1. 集合增删改查
#集合的创建
set1 = {1, 3, 'jason', True, False}
print(set1)


set1 = {'jason', 'carly', 'aloha'}
# 增
# add()
set1.add('sb')
print(set1)
# update()迭代增加
set1.update('abc')
print(set1)

# 删
# remove()按照元素删除
set1.remove('aloha')
print(set1)
# pop()随机删除
set1.pop()
print(set1)
# clear()清空集合
set1.clear()
print(set1)
# del 删除集合
del set1

# 改(变相改值,先删再加)
  1. 集合的交集、并集、差集、反交集
set1 = {1, 2, 3, 4, 5}
set2 = {3, 4, 5, 6, 7}

# 交集
print(set1 & set2)
print(set1.intersection(set2))

# 并集
print(set1 | set2)
print(set1.union(set2))

# 差集
print(set1 - set2)
print(set2 - set1)
print(set1.difference(set2))
print(set2.difference(set2))

# 反交集
print(set1 ^ set2)
print(set1.symmetric_difference(set2))
  1. 集合的子集、超集
set1 = {1, 2, 3}
set2 = {1, 2, 3, 4, 5, 6}

# 子集
print(set1 < set2)
print(set1.issubset(set2))

# 超集
print(set2 > set1)
print(set2.issuperset(set1))

四、深浅拷贝

1.赋值运算

赋值运算让两个列表的内存地址一样, 即id相同,因此不管是修改list1,还是修改list2,另一个列表也会随之改变

list1 = [1, 2, 3, [11, 22, 33]]
list2 = list1
print(id(list1) == id(list2))
# 结果为True,此时list1 和list2 的id是一样的
list1.insert(-1, 666)
list2.pop(1)
list1[-1].append(888)
list2[-1].append(999)
print(list1)
print(list2)   # list1 和 list2 结果一样

2.浅copy

list1 = [1, 2, [11, 22]]
list2 = list1.copy()
print(list1 == list2)  # True
print(id(list1) == id(list2))  # False
# 浅copy: 值相同,但是id不同

list1被创建的时候,内存中被创建了1,2和[11, 22]这三个元素,
我们可以理解成这三个元素放在了内存的某个空间里。
假设list1的id为11111111,则它的三个槽位分别指向这个空间里的1,2,[11, 22]
此时list1浅copy得到了id为22222222的list2,
list2的三个槽位也是分别指向这个空间里的1,2,[11, 22]

# 情况一、如果我们在list1这个列表进行修改,比如追加一个元素,删除一个元素,甚至是清空list1,仅仅是对id为11111111的list1进行了修改,而放在该空间中的1,2,[11, 22]并没有变化。
# 此时list2中的各个槽位指向的仍是该空间中的1,2,[11, 22],因此list2不会改变。
list1 = [1, 2, [11, 22]]
list2 = list1.copy()
list1.append(3)
print(list1)  # 结果为[1, 2, [11, 22], 3]
print(list2)  # 结果为[1, 2, [11, 22]]
# 情况二、如果我们对list1中的[11, 22]进行修改,此时对应在内存中的[11, 22]也会改变。
# 而list2中的[11, 22]也是指向内存中的[11, 22], 内存中的[11, 22]改变了,因此list2中的[11, 22]也随之改变
list1 = [1, 2, [11, 22]]
list2 = list1.copy()
list1[2].append(666)
print(list1)
print(list2)

3.深copy 需要导入copy模块

import copy
list1 = [1, 2, [11, 22]]
list2 = copy.deepcopy(list1)
print(list1 == list2)
print(id(list1) == id(list2))
# 和浅copy一样,值相同,内存地址不同

list1被创建的时候,内存中被创建了1,2,[11, 22]这三个元素, 我们可以理解成这三个元素放在内存的空间一里面
假设list1的id为11111111,则它的三个槽位分别指向空间一里面的1,2,[11, 22]
此时list1深copy得到了id为22222222的list2,与浅copy不同的是,此时内存中在一次创建了1,2,[11, 22]这三个元素,并放在了内存的空间二里面
此时list2的三个槽位分别指向空间二里面的1,2,[11, 22]
此时对list1进行修改,无论怎么修改,list2始终不变,因为list1和list2此时没有任何的关联

import copy
list1 = [1, 2, [11, 22]]
list2 = copy.deepcopy(list1)
list1.append(3)
list1[2].append(666)
print(list1)  # 结果为[1, 2, [11, 22, 666], 3]
print(list2)  # 结果为[1, 2, [11, 22]]

注意:前面理解说两个空间里都有 1,2,[11, 22],这是标准的深copy情形。
但是python做了优化,为了节省内存空间,在python中,int(float) 、str、bool这种不可变的数据类型在内存中只存在一个,因为他们的id都是一样的。

posted @ 2020-03-24 04:11  Jason857  阅读(222)  评论(0编辑  收藏  举报