首页 > 编程语言 >第03天-python字节序列字典

第03天-python字节序列字典

时间:2023-02-09 01:44:06浏览次数:42  
标签:03 set 字节 python image d6 range print 100


1、字节序列和切片
1.1、字节序列
Python3 引入两个新的类型bytes、bytearray。
bytes不可变字节序列;bytearray是可变字节数组。

字节的世界里面没有编码
1.2、编码与解码
编码(encode):str => bytes,将字符串这个字符序列使用指定字符集encode编码为一个个字节组成的序列
bytes
解码(decode):bytes或bytearray => str,将一个个字节按照某种指定的字符集解码为一个个字符串组成的
字符串
pr人int("abc".encdoe()) # 缺省为utf-8编码
print("啊".encode('utf-8'))
print("啊".encode('gbk'))
print(b'abc'.decode('utf8'))
print(b'\xb0\xa1'.decode('gbk'))

字符的世界都有编码

"a\t".encode()    ---->b表示base,\t表示一个字符    #默认utf-8
b'a\t'            ---->encode字符串,通过utf-8编码变成一个个序列

"abc\t".encode('gbk')   ----->gbk双字节编码,编码范围是不同的
b'abc\t'

"啊".encode('utf-8')    ------>utf-8双字节编码,编码范围是不同的
b'\xe5\x95\x8a'         ------>\xe5、\x95、\x8a 一共代表3个字节

"啊".encode('gbk')      ----->gbk双字节编码,编码范围是不同的
b'\xb0\xa1'


b'\xe5\x95\x8a'.decode('utf-8')    ------>decode解码: 二进制 =>字符串
'啊'
b'\xb0\xa1'.decode('gbk')          ------>decode解码: 二进制 =>字符串
'啊' 

 
image-20210907143408157
1.3、ASCII
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁
字母的一套单字节编码系统
熟记:
1. \x00 表中第一项,C语言中的字符串结束符
2. \t \x09 tab字符
3. \r\n \x0d\x0a
4. \x30~\x39 字符0~9,\x31 字符1。注意不是数字1
5. \x41 65 A
6. \x61 97 a
9. \t          16进制 9
10. \n换行     16进制 A
13.  回车      16进制 D
32. 空格       16进制 20
49. 1字符      16进制 31
65. A字符      16进制 41
97. a字符      16进制 61

UTF-8、GBK都兼容了ASCII
'a\x09b\x0d\x0ac \x31\x41\x61' # 表示什么?
'A' > 'a' # 谁大? 

1个字节对应英文字母ASCIT用了128状态,8位最高位0。0~127欧洲,后128个编码

双字节编码65536
Big5
GB2312每个字节的最高位。兼容ASCII
    GBK b'\xb0\xal\' "啊".encode('gbk')
    
全球统一编码:
Unicode双宁节编码。 ------->python3中字符串在内存的编码

utf-8 多字节编码,汉字映射过来一般都要使用3个字节表示
    b'\xe5\x95\x8a' "啊".encode('utf-8')
    
 内存中单个或者多个字节,你如果想按照字符串解读。必须指定编码bytes和bytearray的世界,字节的世界没有字符概念,没有编码的概念,字符串的世界,一定和编码对应
 
 
 0x0d     #---->十六进制的数值表达形式
 13
 
 回车
 '\x0d'    #---->十六进制的字符表达形式
 '\r'
 
 换行
 '\x0a'    #---->十六进制的字符表达形式
 '\n'
 
 x61=a
 '\x0d\x0a\x61'   #---->十六进制的字符表达形式
 '\r\na'
 
 x20=空格
 '\x0d\x0a\x61\x20'  #---->十六进制的字符表达形式,
 '\r\na '  
 
编码:  gbk格式统一
"啊".encode('gbk')                 ------>gbk双字节编码,编码范围是不同的
b'\xb0\xa1'
解码:  gbk格式统一
b'\xb0\xa1'.decode('gbk')          ------>decode解码: 二进制 =>字符串
'啊' 

 
image-20210907163914695
1.4、Bytes初始化
bytes() 空bytes
bytes(int) 指定字节的bytes,被0填充
bytes(iterable_of_ints) -> bytes [0,255]的int组成的可迭代对象
bytes(string, encoding[, errors]) -> bytes 等价于string.encode()
bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer 从一个字节序列或者buffer复制
出一个新的不可变的bytes对象

使用b前缀定义
    只允许基本ASCII使用字符形式b'abc9'
    使用16进制表示b"\x41\x61"
    
    
bytes类型和str类型类似,都是不可变类型,操作方法类似。
print(b'abcd'[2]) # 返回int,指定是本字节对应的十进制数



bytes(),b'',b'abc',b'\61\x62\x63'   #----->\61\x62\x63在内存中是三个字节,不是字符串和整型
(b'', b'', b'abc', b'abc')

bytes(5)     #---->5个字节的bytes,五个字节都是0
b'\x00\x00\x00\x00\x00'

bytes(range(49,55))
b'123456'

bytes(range(97,100))
b'abc'

bytes(range(0x41,0x45))
b'ABCD'

bytes(range(0x41,0x45,2)),bytes([97,99,101])
(b'AC', b'ace')

b1 = b'abc'       ------>b1与b2内存地址指向同一个位置
b2 = bytes(b1)
print(b1,b2,b1==b2, id(b1),id(b2))
b'abc' b'abc' True 1827712687800 1827712687800

s1 = 'abc'        ------->s1与s2与s3内存地址指向同一位置
s2 = 'abc'
print(s1==s2, s1 is s2)
s3 = str(s1)
print(s3 is s1)
True True
True

bytes('abc','utf-8'),'abc'.encode()
(b'abc', b'abc')

bytes(range(10))[-1]
9

b'abc'[-2]
98

 
image-20210907170136621

 
image-20210907170928401

 
image-20210907171710197

 
image-20210907172346476
1.5、bytearray初始化
bytearray() 空bytearray
bytearray(int) 指定字节的bytearray,被0填充
bytearray(iterable_of_ints) -> bytearray [0,255]的int组成的可迭代对象
bytearray(string, encoding[, errors]) -> bytearray 近似string.encode(),不过返回可变对象
bytearray(bytes_or_buffer) 从一个字节序列或者buffer复制出一个新的可变的bytearray对象
b前缀表示的是bytes,不是bytearray类型
由于bytearray类型是可变数组,所以,类似列表。


append(int) 尾部追加一个元素
insert(index, int) 在指定索引位置插入元素
extend(iterable_of_ints) 将一个可迭代的整数集合追加到当前bytearray
pop(index=-1) 从指定索引上移除元素,默认从尾部移除
remove(value) 找到第一个value移除,找不到抛ValueError异常
注意:上述方法若需要使用int类型,值在[0, 255]
clear() 清空bytearray
reverse() 翻转bytearray,就地修改

b = bytearray()
b.append(97)
b.append(99)
b.insert(1,98)
b.extend([65,66,67])
b.remove(66)
b.pop()
b.reverse()
print(b) # 输出什么
b.clear()
1.5.1、bytearray
bytearray()
bytearray(b'')

x = bytearray(range(0x41,70,2))
x
bytearray(b'ACE')

追加:
x.append(0x31)
x
bytearray(b'ACE1')

扩展:
x.extend(b'897')
x
bytearray(b'ACE1897')

pop_从指定索引上移除元素,默认从尾部移除
x.pop()
55

remove_找到第一个value移除,找不到抛ValueError异常
x.remove(0x39)
bytearray(b'ACE18')

extend_将一个可迭代的整数集合追加到当前bytearray
x.extend(range(0x31,0x35))
bytearray(b'ACE181234')

 
image-20210907174645423

 
image-20210908112637372
1.6、线性结构
线性结构特征:
    可迭代 for ... in
    有长度,通过len(x)获取,容器
    通过整数下标可以访问元素。正索引、负索引
        可以切片
已经学习过的线性结构:list、tuple、str、bytes、bytearray
1.6.1、切片
sequence[start:stop]
sequence[start:stop:step]

通过给定的索引区间获得线性结构的一部分数据
start、stop、step为整数,可以是正整数、负整数、零
start为0时,可以省略
stop为末尾时,可以省略
step为1时,可以省略
切片时,索引超过上界(右边界),就取到末尾;超过下界(左边界),取到开头

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[:])                  ---->从头至尾
print(x[:-1]) #              ---->不要倒数第一个
print(x[0:])                 ---->包含头包含末尾都要
print(x[3:])                 ---->从索引3开始向后取
print(x[3:-1]) #             ---->从索引3开始向后取不要末尾
print(x[9:])                 ---->从9向后取,只能取到9
print(x[:9])                 ---->从头取到9,9不包含
print(x[9:-1])               ---->[9,-1]等于9到9,什么都取不到
print(x[:100])               ---->从头到尾
print(x[-100:])              ---->从头到尾
print(x[4:-2])               ---->[4,-2]到8从后往前
print(x[-4:-2])              ---->[-4:-2]为6到8,不包含8,所以为6,7
print('0123456789'[-4:8])    ---->类型不变照样切片
print(b'0123456789'[-4:8])
print(bytearray(b'0123456789')[-10:5])



x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[::])                 ---->间隔一个走,[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[::2])                ---->间隔两个走,[0,2,4,6,8]
print(x[2:8:3])              ---->间隔三个走,[0,2,5],不包含8
print(x[:9:3])               ---->间隔三个走,[0,3,6],不包含9
print(x[1::3])               ---->从1开始三个走,[1,4,7]
print(x[-10:8:2])            ---->-10为0,从0开始两个走,[0,2,4,6],不含8



# 起止和方向
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[-10:])               ---->0到尾,正着走,步长为1
print(x[-5:6])               ---->5到6,出一个5
print(x[-5:-6])              ---->5到4,为空''列表,方向不对
print(x[6:5])                ---->6到5,为空''列表,方向不对
print(x[5:5])                ---->5到5,前包后不包,出不来
print(x[1:9:-2])             ---->1到9,-2为左,方向不对,出不来
print(x[::-2])               ---->9到0,[9,7,5,3,1]
print(x[8::-2])              ---->8到0,[8,6,4,2,0]
print(x[8:2:-2])             ---->8到2, [8,6,4],不包含2
print(x[8:-10:2])            ---->8到0,正2走不行
print(x[8:-10:-2])           ---->8到0,[8,6,4,2],不包含0
print(x[-5:4:-1])            ---->5到4,倒着走一个,[5],不包含4
print(x[-5:5:-1])            ---->5到5,走-1,前包后不包,出不来


在序列上使用切片[start:stop],子区间索引范围[start, stop),相当于从start开始指向stop的方向上获取数据
默认step为1,表示向右;步长为负数,表示向左
如果子区间方向和步长方向不一致,直接返回当前类型的"空对象"
如果子区间方向和步长方向一致,则从起点间隔步长取值
x
bytearray(b'ACE181234')

x[1:3]   #range 前包后不包
bytearray(b'CE')

x[:]    #从头至尾
bytearray(b'ACE181234')

x[1:]   #------>掐头,第一个元素不要 
bytearray(b'CE181234')

x[:-1] #------->从头去掉尾部,倒数第一个不要
bytearray(b'ACE18123')


x = bytes(range(0x30,0x3a))
x
b'0123456789'

切片:
x[1:3]        ----->切除前包后不包对象b'12'
b'12'

x[1:-1],x[-9:-1],x[2:] , x[:-2]
(b'12345678', b'12345678', b'23456789', b'01234567')

x[::1],x[::2],x[1::2],x[::3],x[:-1:3]
(b'0123456789', b'02468', b'13579', b'0369', b'036')

x[-100:100]
b'0123456789'

x[-100:100],x[-100:100:3]  #----->从头到尾来3步一走
(b'0123456789', b'0369')

x[::-1]   #----->从尾到头逆着取
b'9876543210'

x[::-2],x[1::-2],x[0:10:-2]
(b'97531', b'1', b'') 

x[::-2],x[2::-2],x[0:10:-2]
(b'97531', b'20', b'')

x[1::-1]   ---->从右取两个元素
b'10'

x[1:-1:-1]
b''

x[4::-2]
b'420'
内建函数	函数签名	说明
id	id(object)	CPython中返回对象的内存地址可以用来判断是不是同一个对象
# 使用id看地址,要注意地址回收复用问题
print(id([1,2,3]))
print(id([4,5,6,7]))
# 上下两句可能内存地址一样,但是上面那个[1,2,3]没有意义,因为它用完之后,引用计数为0了,没人能再次访问到,释放了内存
# 如果2个存在在内存中的对象,地址一样一定是同一个对象

 
image-20210908114211090

 
image-20210908143403557

 
image-20210908143430227

 
image-20210908144719604

 
image-20210908145213974

 
image-20210908145801763

 
image-20210908145322082

 
image-20210908145506579

 
image-20210908150643115
1.6.2、本质
x = [0, 1, 2]
y = x[:]
print(x, y)
print(id(x), id(y))
x[0] = 100
print(x, y)


x = [[1]]
y = x[:]
print(x, y)
print(x == y)
print(id(x), id(y), x is y)
x[0][0] = 100
print(x, y)
print(x == y)
print(x is y)
x[0] = 200
print(x == y) # ?
print(x, y)

上例可知,实际上切片后得到一个全新的对象。[:] 或[::] 相当于copy方法。


切片1:
x = b'0123'
x
b'0123'

y = x[:]
z = x[::]

x == y, x == z
(True, True)


切片2:
x = [0,1,2,3]                    ------->切片后,为不同的内存地址
y = x[:]
z = x[::]
print(x == y, x==z)
print(x is y, x is z )
print(id(x),id(y),id(z))
True True
False False
3118976041800 3118976055816 3118973425224


切片3:
x = 'abc'
y = x[:]
m = x[::1]
n = x[::2]

id(x),id(y),id(m),id(n),x,y,m,n
(3118903062632,
 3118903062632,
 3118903062632,
 3118986707552,
 'abc',
 'abc',
 'abc',
 'ac')
 
 

切片4:
x = [1,2,3]
y = x[:]
print(1, x == y, x is y,x,y)
x[1] = 100
print(2, x == y, x,y)
1 True False [1, 2, 3] [1, 2, 3]
2 False [1, 100, 3] [1, 2, 3]

x = [1,[2,3,4],5]
y = x[::]          #----->浅拷贝
print(1,x == y, x is y)
x[1][1] = 200
print(2,x == y ,x is y,x,y)
x[1] = 400
# print(3, x == y, x is y,x,y)
print(4,x == y, x is y,x,y)
1 True False
2 True False [1, [2, 200, 4], 5] [1, [2, 200, 4], 5]
4 False False [1, 400, 5] [1, [2, 200, 4], 5]


pyCharm
x = [1,2,3,4,5]
print(id(x))
print(id([1,2,3,4,5]))   #--->在同一个内存地皮上创建的,前一个创建完就被释放,后一个在同一块地皮上            #--->所以造成地址一样                       
print(id([5,55,66]))
1861846323720
1861846324232
1861846324232

 
image-20210908160030316

 
image-20210908160531999

 
image-20210908161101039

 
image-20210908163839204

 
image-20210908170352848
2、集合
2.0、封装和解构
2.0.1、简介
基本概念
t1 = 1, 2
print(type(t1)) # 什么类型

t2 = (1, 2)
print(type(t2))

Python等式右侧出现逗号分隔的多值的时候,就会将这几个值封装到元组中。这种操作称为封装
packing。

x, y = (1, 2)
print(x) # 1
print(y) # 2

Python中等式右侧是一个容器类型,左侧是逗号分隔的多个标识符,将右侧容器中数据的一个个和左侧
标识符一一对应。这种操作称为解构unpacking。
从Python3开始,对解构做了很大的改进,现在用起来已经非常的方便快捷。


封装和解构是非常方便的提取数据的方法,在Python、JavaScript等语言中应用极广。
# 交换数据
x = 4
y = 5
t = x
x = y
y = t
2.0.2、简单解构
# 左右个数相同
a,b = 1,2
a,b = (1,2)
a,b = [1,2]
a,b = [10,20]
a,b = {10,20} # 非线性结构
a,b = {'a':10,'b':20} # 非线性结构也可以解构
[a,b] = (1,2) # 等号左边只能是元组或列表
[a,b] = 10,20
(a,b) = {30,40}


那么,左右个数不一致可以吗?
a, b = (10, 20, 30)         ---->不能

# 封装和解构,交换
x = 10
y = 11
x, y = y, x

t = 1,2           ----->封装成tuple元组
type(t),t
(tuple, (1, 2))    

x,y = {11,12}     ----->set集合
x,y
(11, 12)

x, y = range(2)   ----->两边都要相同的数,解构必须x,y数相同
x,y
(0, 1)

[x,y] = 100,101
x,y
(100, 101)

[x,y] = [7,9]     ----->解构时,等式左边标识符如果可以只能写成元组或者列表
x,y
(7, 9)

x = 7             ----->元素交换
y = 9

t = x 
x = y 
y = t
x,y
(9, 7)

x = 7 
y = 11 
x,y = y, x
print(x,y)
11 7

 
image-20210909131650416

 
image-20210910143310239

 
image-20210910143920585

 
image-20210910144120448
2.2.1、rest剩余的变量
在Python3.0中增加了剩余变量解构(rest)。
a, *rest, b = [1, 2, 3, 4, 5]
print(a, b)
print(type(rest), rest) # <class 'list'> [2, 3, 4]

标识符rest将尽可能收集剩余的数据组成一个列表。
a, *rest = [1, 2, 3, 4, 5]
print(a, rest)

*rest, b = [1, 2, 3, 4, 5]
print(rest, b)

*rest = [1, 2, 3, 4, 5]
print(rest) # 内容是什么?

a, *r1, *r2, b = [1, 2, 3, 4, 5] # ?   
它出来的一定是一个列表

a, *_, b = [1, 2, 3, 4, 5]
print(_) # 在IPython中实验,_是最后一个输出值,这里将把它覆盖

_, *b, _ = [1, 2, 3]
print(_) # 第一个_是什么
print(b) # 是什么
print(_) # 第二个_是什么

_是合法的标识符,这里它没有什么可读性,它在这里的作用就是表示不关心这个变量的值,我不想要。有人把它称作 丢弃(Throwaway)变量。

练习:
从nums = [1, (2, 3, 4), 5]中,提取其中4出来
nums = [1,(2,3,4),5]
print(nums[1][-1])       ---->相同
[_,(*_,x),_] = nums      ---->相同
print(x)
4
4
_,(*_,x),_=nums          ---->相同
x
4
从list(range(10))中,提取第二个、第四个、倒数第二个元素
m = list(range(10))
m
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_,s,_,f,*_,l,_ = m       ---->提取第二个、第四个、倒数第二个元素
s,f,l
(1, 3, 8)



x, *rest = [1,2,3,4,5]    ------>剩余收集
x
1
rest                      ------>剩余收集
[2, 3, 4, 5]

*rest, y = [1,2,3,4,5]   
rest                      ------>剩余收集
[1, 2, 3, 4]
y
5
 
a, *b, c = [1,2,3,4,5,6]  ------->剩余收集
a,b,c
(1, [2, 3, 4, 5], 6)

a, *b = {'a',123,1}       ------->剩余收集
a
1
b
['a', 123]



字典:
m,n = {'a':1, 'b':'abc'}  ------>取的是元素的key
m
'a'
n
'b'

head, *_,tail = range(1,100)    ------>解构
head
1
tail
99

a,*_,b = [1,2,3]           ------>剩余收集
a,b,_
(1, 3, [2])

a, *_,b  = 1,2             ------>剩余收集
a,b,_
(1, 2, [])

_, *a,_,b = 1,2,3,4
print(1,_)                 ------>下划线为3
1 3               
print(2,a)
2 [2]
print(3,_)                 ------>下划线为3
3 3
print(4,b)
4 4 

 
image-20210911161011286

 
image-20210911163709070

 
image-20210911163948592

 
image-20210913100459675

 
image-20210913101018863

 
image-20210913101220376

 
image-20210913101728897

 
image-20210913103045528

 
image-20210913103453822
2.2.1.1、报错点
*rest = (1,2,3,4,5)
SyntaxError: starred assignment target must be in a list or tuple (<ipython-input-7-028ca57a2d78>, line 4)
  File "<ipython-input-7-028ca57a2d78>", line 4
SyntaxError: starred assignment target must be in a list or tuple

*rest = range(1,6)
SyntaxError: starred assignment target must be in a list or tuple (<ipython-input-7-028ca57a2d78>, line 4)
  File "<ipython-input-7-028ca57a2d78>", line 4
SyntaxError: starred assignment target must be in a list or tuple

rest?
Type:        list
String form: [1, 2, 3, 4]
Length:      4
Docstring:  
list() -> new empty list
list(iterable) -> new list initialized from iterable's items


a, *b, c ,*d= [1,2,3,4,5,6]    #------> *b,*d值必须要是能够确认的值
SyntaxError: two starred expressions in assignment (<ipython-input-22-bac9b67fbcb7>, line 4)
  File "<ipython-input-22-bac9b67fbcb7>", line 4
SyntaxError: two starred expressions in assignment
2.1、集合Set
集合,简称集。由任意个元素构成的集体。高级语言都实现了这个非常重要的数据结构类型。
Python中,它是可变的、无序的、不重复的元素的集合。
{1, 'a', (1,2, ((1,[]), 1))}

(1,[])   ---->元组
[]       ---->列表
'a'      ---->字符
2.1.1、set()集合
set() -> new empty set object
set(iterable) -> new set object

s1 = set()
s2 = set(range(5))
s3 = set([1, 2, 3])
s4 = set('abcdabcd')
s5 = {} # 这是什么?
s6 = {1, 2, 3}
s7 = {1, (1,)}
s8 = {1, (1,), [1]} # ?


set(), set(range(5)),set([1,2,3,2,5])    ------>去重
(set(), {0, 1, 2, 3, 4}, {1, 2, 3, 5})

{1,2},{1,2,3,1,2},{'1',1,(1,)}           ------>无序
({1, 2}, {1, 2, 3}, {(1,), 1, '1'})

s1 = {'a','b','c','d'}                   ------>无序
print(s1)
{'b', 'a', 'c', 'd'}

y = set('abcdabcd')                     ------>去重
y
{'a', 'b', 'c', 'd'}

{1,'a',(1,2), [1]}          ----->报错,为不可识别hash
{1,'a',(1,2,[1])}           ----->报错,为不可识别hash

 
image-20210913140045222

 
image-20210913141413601
2.2、初始化
set() -> new empty set object
set(iterable) -> new set object


s1 = set()
s2 = set(range(5))
s3 = set([1, 2, 3])
s4 = set('abcdabcd')
s5 = {} # 这是什么?
s6 = {1, 2, 3}
s7 = {1, (1,)}
s8 = {1, (1,), [1]} # ?
2.2.1、成员运算符in
print(10 in [1, 2, 3])
print(10 in {1, 2, 3})

上面2句代码,分别在列表和集合中搜索元素。如果列表和集合的元素都有100万个,谁的效率高?

hash((1,(1,)))
178206445556
hash函数,散列函数,一个微小的变化,都会引起hash结果的巨大变化

hash('a')     ----->在不同解释器上,能够有不同的结果

%timeit (-1 in [1,2,3])  ----->-1在列表[1,2,3]中的执行速度, 99.1纳秒
99.1 ns ± 9.3 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)


 
image-20210913142906926

 
image-20210913143551018
2.2.1.1、IPython魔术方法
IPython内置的特殊方法,使用%百分号开头的
    % 开头是line magic
    %% 开头是 cell magic,notebook的cell


%timeit statement
-n 一个循环loop执行语句多少次
-r 循环执行多少次loop,取最好的结果

%%timeit setup_code
* code.....



# 下面写一行,列表每次都要创建,这样写不好
%timeit (-1 in list(range(100)))

# 下面写在一个cell中,写在setup中,列表创建一次
%%timeit l=list(range(1000000))
-1 in l


集合元素未建立好
================
list遍历
列表找元素的性能,高于同规模的集合set
-----------------------------------
%timeit (-1 in set(range(100)))   ----->执行时间为5.64微秒
5.64 µs ± 256 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit (-1 in list(range(100)))  ----->执行时间为4.06微秒
4.06 µs ± 496 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)


%timeit (-1 in list(range(10000000)))  ------>检测-1是否存在列表中,则为683毫秒
683 ms ± 100 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit (-1 in list(range(10000000))) ------>检测-1是否存在列表中,则为920毫秒
920 ms ± 63.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)


集合元素建立好
===============
hash空间换时间
列表找元素的性能,低于同规模的集合set
------------------------------------
%%timeit t=list(range(100))  #cell magic %%timeit setup 只做一次,初始化代码          
-1 in t                    -------> 耗时2.09微妙
2.09 µs ± 57.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit t=set(range(100)) 
-1 in t                    -------> 耗时56.4纳秒
56.4 ns ± 5.92 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

 
image-20210913143737176

 
image-20210913144439162

 
image-20210913145924210
2.2.1.2、set和线性结构比较
结果说明,集合性能很好。为什么?

    线性数据结构,搜索元素的时间复杂度是O(n),即随着数据规模增加耗时增大
    set、dict使用hash表实现,内部使用hash值作为key,时间复杂度为O(1),查询时间和数据规模无关,不会随着数据规模增大而搜索性能下降。

 
image-20210913152310205
2.3、元素性质
去重:在集合中,所有元素必须相异
无序:因为无序,所以不可索引
可哈希:Python集合中的元素必须可以hash,即元素都可以使用内建函数hash
目前学过不可hash的类型有:list、set、bytearray
可迭代:set中虽然元素不一样,但元素都可以迭代出来

不可hash类型(不能放在set中作为元素的):
list、set、 bytearray
2.4、增加
add(elem)
    增加一个元素到set中
    如果元素存在,什么都不做
update(*others)
    合并其他元素到set集合中来
    参数others必须是可迭代对象
    就地修改

s = set()
s.add(1)
s.update((1,2,3), [2,3,4])
2.5、删除
remove(elem)
    从set中移除一个元素
    元素不存在,抛出KeyError异常。为什么是KeyError?
discard(elem)
    从set中移除一个元素
    元素不存在,什么都不做
 
pop() -> item
移除并返回任意的元素。为什么是任意元素?
空集返回KeyError异常

clear()
移除所有元素


s = set(range(10))
s.remove(0)
#s.remove(11) # KeyError为什么
s.discard(11)
s.pop()
s.clear()
2.6、修改
集合类型没有修改。因为元素唯一。如果元素能够加入到集合中,说明它和别的元素不一样。
所谓修改,其实就是把当前元素改成一个完全不同的元素,就是删除加入新元素。
2.7、索引
非线性结构,不可索引。
2.8、遍历
只要是容器,都可以遍历元素。但是效率都是O(n)
2.9、可哈希
    数值型int、float、complex
    布尔型True、False
    字符串string、bytes
    tuple
    None
    以上都是不可变类型,称为可哈希类型,hashable
set元素必须是可hash的。


不可hash:
字典
3.0、集合概念
全集
    所有元素的集合。例如实数集,所有实数组成的集合就是全集
子集subset和超集superset
    一个集合A所有元素都在另一个集合B内,A是B的子集,B是A的超集
真子集和真超集
    A是B的子集,且A不等于B,A就是B的真子集,B是A的真超集
并集:多个集合合并的结果
交集:多个集合的公共部分
差集:集合中除去和其他集合公共部分
3.0.1、并集
将两个集合A和B的所有的元素合并到一起,组成的集合称作集合A与集合B的并集
    union(*others) 返回和多个集合合并后的新的集合
    | 运算符重载,等同union
    update(*others) 和多个集合合并,就地修改
    |= 等同update

 
image-20210913152750694
3.0.2、并集
集合A和B,由所有属于A且属于B的元素组成的集合
    intersection(*others) 返回和多个集合的交集
    & 等同intersection
    intersection_update(*others) 获取和多个集合的交集,并就地修改
    &= 等同intersection_update
3.0.3、差集
集合A和B,由所有属于A且不属于B的元素组成的集合
    difference(*others) 返回和多个集合的差集
    - 等同difference
    difference_update(*others) 获取和多个集合的差集并就地修改
    -= 等同difference_update

 
image-20210913153001341
3.0.4、对称差集
集合A和B,由所有不属于A和B的交集元素组成的集合,记作(A-B)∪(B-A)
    symmetric_differece(other) 返回和另一个集合的对称差集
    ^ 等同symmetric_differece
    symmetric_differece_update(other) 获取和另一个集合的对称差集并就地修改
    ^= 等同symmetric_differece_update
3.0.5、其它集合运算
    issubset(other)、<= 判断当前集合是否是另一个集合的子集
    set1 < set2 判断set1是否是set2的真子集
    issuperset(other)、>= 判断当前集合是否是other的超集
    set1 > set2 判断set1是否是set2的真超集
    isdisjoint(other) 当前集合和另一个集合没有交集,没有交集,返回True

练习:
一个总任务列表,存储所有任务。一个已完成的任务列表。找出为未完成的任务

业务中,任务ID一般不可以重复
所有任务ID放到一个set中,假设为ALL
所有已完成的任务ID放到一个set中,假设为COMPLETED,它是ALL的子集
ALL - COMPLETED => UNCOMPLETED
集合运算,用好了妙用无穷。
3、dict字典
Dict即Dictionary,也称为mapping。

Python中,字典由任意个元素构成的集合,每一个元素称为Item,也称为Entry。这个Item是由(key,
value)组成的二元组。

字典是可变的、无序的、key不重复的key-value键值对集合。

字典不可hash
3.1、dict初始化字典
    dict(**kwargs) 使用name=value(值)对初始化一个字典
    dict(iterable, **kwarg) 使用可迭代对象和name=value对构造字典,不过可迭代对象的元素
    必须是一个二元结构**
    dict(mapping, **kwarg) 使用一个字典构建另一个字典
    
    
字典的初始化方法都非常常用,都需要会用
d1 = {}
d2 = dict()
d3 = dict(a=100, b=200)
d4 = dict(d3) # 构造另外一个字典

# 类方法dict.fromkeys(iterable, value)
d = dict.fromkeys(range(5))
d = dict.fromkeys(range(5), 0)
d5 = dict(d4, a=300, c=400)
d6 = dict([('a', 100), ['b', 200], (1, 'abc')], b=300, c=400)


创建二元结构字典
dict(), dict([(1,2)]), dict([(1,2),  ('a',100),  ['b',123]]) 
({},          {1: 2},       {1: 2,   'a': 100,   'b': 123})

x = dict([(1,2), ('a',100), ['b',123]])
x
{1: 2,   'a': 100,   'b': 123}


等式前后的id不同
y = dict(x)                                  ------>id不同
print(y, id(y))
{1: 2, 'a': 100, 'b': 123} 2739359977904

print(x, id(x))                              ------>id不同
{1: 2, 'a': 100, 'b': 123} 2739348965344


创建字典,并修改a与c的值
d2 = dict([(1,2),('a',100),['b',123]],a=200,c=201)  
d2
{1: 2, 'a': 200, 'b': 123, 'c': 201}
print(d3)
{1: 2, 'a': 400, 'b': 500, 'c': 201, 'd': 600}



修改a与c的值,并添加字典b,d
d5 = dict(a=400,b=500,c=201,d=600)       ---->构造字典
d5.update([(1,2)])
print(d5)
{'a': 400, 'b': 500, 'c': 201, 'd': 600, 1: 2}

 
image-20210913165201194

 
image-20210913170744367

 
image-20210913171617436

 
image-20210913172417915

 
image-20210913173217320

 
image-20210913225158594
3.2、元素访问
d[key]
    o 返回key对应的值value
    o key不存在抛出KeyError异常
get(key[, default])
    o 返回key对应的值value
    o key不存在返回缺省值,如果没有设置缺省值就返回None
setdefault(key[, default])
    o 返回key对应的值value
    o key不存在,添加kv对,value设置为default,并返回default,如果default没有设置,缺省为None
3.2.1、 dict.fromkeys(字典.从键)
对从键设置向对应的value值

dict.fromkeys('abcdefg')              ---->构造字典
{'a': None, 'b': None, 'c': None, 'd': None, 'e': None, 'f': None, 'g': None}

dict.fromkeys(['abc'],1)              ---->构造字典
{'abc': 1}

dict.fromkeys(['abc',  1,  '2',  (1,)],  7)   ---->构造字典
{'abc': 7,   1: 7,    '2': 7,    (1,): 7}

d6 = dict.fromkeys('abc',[1])         ---->构造字典
print(d6)
d6['a'][0] = 100
print(d6)
{'a': [1], 'b': [1], 'c': [1]}
{'a': [100], 'b': [100], 'c': [100]}

d6 = dict.fromkeys('abc',[1])         ---->构造字典
print(d6)
d6['a'][0] = 100
print(d6)
{'a': [1], 'b': [1], 'c': [1]}
{'a': [100], 'b': [100], 'c': [100]

  
d6                        
d6['a'] 
d6['a'] = 1                    ------>已经存在就修改
d6['g']  = 222                 ------>不存在就创建
d6
{'a': 1, 'b': [100], 'c': [100], 'g': 222}
3.2.2、get
d6['a'],d6.get('a'),d6.get('d',b'')           ----->找不到的元素给缺省值
([100], [100], b'')
3.2.3、setdefault
d6.setdefault('a'),d6.setdefault('b')        ----->取值  
([100], [100])

d6.setdefault('a'),d6.setdefault('b'),d6.setdefault('d')   ----->取值
([100], [100], None)      --->先判断键值对,key不存在,使用default默认None创建键值对,如果key相当于get

d6.setdefault('e',123)    ---->键值对不存在,给出缺省值
123
3.3、新增和修改
d[key] = value
    将key对应的值修改为value
    key不存在添加新的kv对
update([other]) -> None
    使用另一个字典的kv对更新本字典
    key不存在,就添加
    key存在,覆盖已经存在的key对应的值
    就地修改
d = {}
d['a'] = 1
d.update(red=1)
d.update(['red', 2])
d.update({'red':3})
3.3.1、update增加
d6
{'a': 1, 'b': [100], 'c': [100], 'g': 222}
d6.update(b=224,d=567)                       ----->存在即修改,不存在就创建
d6
{'a': 1, 'b': 224, 'c': [100], 'g': 222, 'd': 567}

d6.update({'a':'abc','c':111},a=1111,b=3333)  ----->修改元素
{'a': 1111, 'b': 3333, 'c': 111, 'g': 222, 'd': 567}
3.3.2、pop删除
remove(elem)
    从set中移除一个元素
    元素不存在,抛出KeyError异常。为什么是KeyError?
discard(elem)
    从set中移除一个元素
    元素不存在,什么都不做
pop() -> item
    移除并返回任意的元素。为什么是任意元素?
    空集返回KeyError异常
clear()
    移除所有元素
    
s = set(range(10))
s.remove(0)
#s.remove(11) # KeyError为什么
s.discard(11)
s.pop()
s.clear()


d6.pop('g') 
d6
{'a': 1111, 'b': 3333, 'c': 111}

if 'a' in d6:             ----->元素a存在打印a
    print('in')
in

 
image-20210913231334090
3.4、遍历
3.4.1、Key键=set(可hash)
for k in d:
    print(k)
    
for k in d.keys():
    print(k)


pop删除'g'
----------
d6.pop('g')
d6
{'a': 1111, 'b': 3333, 'c': 111, 'e': 123, 'd': 567}



遍历key两种方法:
--------------
1、
for k in d6:              ------>遍历key键,等价
    print(k)
a
b
c

2、
for k in d6.keys():       ------>遍历key键,等价
    print(k)
a
b
c
3.4.2、Value值(可hash)
for v in d.values():
    print(v)
     
for k in d.keys():
    print(d[k])
    print(d.get(k))



遍历value两种方法:
-----------------
d6
{'a': 1111, 'b': 3333, 'c': 111, 'e': 123, 'd': 567}

1、
for v in d6.values():                             ------>输出value值
    print(v)
1111
3333
111

2、
for k in d6:                                      ------>输出value值
    print(k, d6.get(k), d6[k], d6.setdefault(k))
a 1111 1111 1111
b 3333 3333 3333
c 111 111 111
3.4.3、Item项目=set(可hash)
for item in d.items():
    print(item)
    print(item[0], item[1])
    
for k,v in d.items():
    print(k, v)
    
for k,_ in d.items():
    print(k)
    
for _,v in d.items():
    print(v)

Python3中,keys、values、items方法返回一个可迭代对象
    Dictionary view对象,可以使用len()、iter()、in操作
    字典的entry的动态的视图,字典变化,视图将反映出这些变化
    keys返回一个类set对象,也就是可以看做一个set集合。如果values都可以hash,那么items也可
    以看做是类set对象
    
Python2中,上面的方法会返回一个新的列表,立即占据新的内存空间。所以Python2建议使用iterkeys、itervalues、iteritems版本,返回一个迭代器,而不是返回一个copy


遍历items拿出二元组
=====================
d6.update(a=222, d=567)
d6
{'a': 222, 'b': 3333, 'c': 111, 'e': 123, 'd': 567, '123': [123]}


items生成二元组,并拿去keys与value值
for item in d6.items():    ----->item[0]为键,item[1]为值
  print(item,      item[0],   item[1])
('a', 1111)二元组   a(keys)      1111(value)
('b', 3333)二元组   b(keys)      3333(value)
('c', 111) 二元组   c(keys)      111 (value)


keys键和value值
for (k,v) in d6.items():     ----->keys键和value值
    print(k,v)
a 1111
b 3333
c 111

value值
for _,v in d6.items():       ----->打印value值
    print(v)
1111
3333
111

 
image-20210913231922113

 
image-20210913232728184

 
image-20210913233113793
3.4、遍历与删除
d6.update([('123',[123])])# 错误的做法
d = dict(a=1, b=2, c=3)
for k,v in d.items():
    print(d.pop(k))
  
  
set_二元组hash运算:
set(d6.keys()),set(d6.values()),set(d6.items())
({'a', 'b', 'c', 'd'},
 {111, 222, 567, 3333},
 {('a', 222), ('b', 3333), ('c', 111), ('d', 567)})
 
update_dict字典中添加一项: 
d6.update([('123',[123])])
d6
{'a': 222, 'b': 3333, 'c': 111, 'd': 567, '123': [123]}

set_keys可hash运算:
set(d6.keys())              -------> key
{'123', 'a', 'b', 'c', 'd'}


items并集运算:
d6.keys() | {1,2,3}        
{1, 2, 3, 'a', 'b', 'c'}

d6.items() | {1,2,3}

set(d6.values()) | {1,2,3}

items,keys,set不允许使用删除pop:     
for k,v in d6.items():
    print(k,v)
    d6.pop(K)                ----->使用会报错,但会执行
a [100]
b [100]
c [100]

条件判断:
删除长度len(d5)的元素
d5
{'a': 400, 'b': 500, 'c': 201, 'd': 600, 1: 2}
while len(d5):
    d5.popitem()
    d5
()

添加keys元素:
keys = []
for k,v in d6.items():
    print(k,v)
    if v % 2 == 0:
        keys.append(k)
print(keys)

移除元素
for k in keys:
    d6.pop(k)

 
image-20210913235225597

 
image-20210915001314862

 
image-20210915001502894

 
image-20210915002442423

 
image-20210915003315505

 
image-20210915003525874
3.5、key
字典的key和set的元素
    set的元素可以就是看做key,set可以看做dict的简化版
    hashable 可哈希才可以作为key,可以使用hash()测试
    使用key访问,就如同列表使用index访问一样,时间复杂度都是O(1),这也是最好的访问元素的方式
    
    d = {
        1 : 0,
        2.0 : 3,
        "abc" : None,
        ('hello', 'world', 'python') : "string",
        b'abc' : '135'
}
3.6、有序性
字典元素是按照key的hash值无序存储的。
但是,有时候我们却需要一个有序的元素顺序,Python 3.6之前,使用OrderedDict类可以做到,3.6开始dict自身支持。到底Python对一个无序数据结构记录了什么顺序?

# 3.5如下
C:\Python\Python353>python
Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit
(AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'a':300, 'b':200, 'c':100, 'd':50}
>>> d
{'c': 100, 'a': 300, 'b': 200, 'd': 50}
>>> list(d.keys())
['c', 'a', 'b', 'd']
>>> exit()


C:\Python\Python353>python
Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit
(AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'a':300, 'b':200, 'c':100, 'd':50}
>>> d
{'b': 200, 'c': 100, 'd': 50, 'a': 300}
Python 3.6之前,在不同的机器上,甚至同一个程序分别运行2次,都不能确定不同的key的先后顺序。
# 3.6+表现如下
C:\Python\python366>python
Python 3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 03:37:03) [MSC v.1900 64 bit
(AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'c': 100, 'a': 300, 'b': 200, 'd': 50}
>>> d
{'c': 100, 'a': 300, 'b': 200, 'd': 50}
>>> exit()

C:\Python\python366>python
Python 3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 03:37:03) [MSC v.1900 64 bit
(AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'c': 100, 'a': 300, 'b': 200, 'd': 50}
>>> d
{'c': 100, 'a': 300, 'b': 200, 'd': 50}
>>> d.keys()
dict_keys(['c', 'a', 'b', 'd'])

Python 3.6+,记录了字典key的录入顺序,遍历的时候,就是按照这个顺序。
如果使用d = {'a':300, 'b':200, 'c':100, 'd':50} ,就会造成以为字典按照key排序的错觉。
目前,建议不要3.6提供的这种字典特性,还是以为字典返回的是无序的,可以在Python不同版本中考虑使用OrderedDict类来保证这种录入序。

t4.py
from collections import  OrderedDict  # sort,OrderedDict有序字典
d = OrderedDict()
d.update(a=1, c=2, d=3, b=4)
print(d)
OrderedDict([('a', 1), ('c', 2), ('d', 3), ('b', 4)])

 
image-20210915005026368
4、解析式
4.1、列表解析式
列表解析式List Comprehension,也叫列表推导式
# 生成一个列表,元素0~9,将每一个元素加1后的平方值组成新的列表
x = []
for i in range(10):
    x.append((i+1)**2)
print(x)


语法
    [返回值 for 元素 in 可迭代对象 if 条件]
    使用中括号[],内部是for循环,if条件语句可选
    返回一个新的列表


列表解析式是一种语法糖
    编译器会优化,不会因为简写而影响效率,反而因优化提高了效率
    减少程序员工作量,减少出错
    简化了代码,增强了可读性


[expr for item in iterable if cond1 if cond2]
等价于
ret = []
for item in iterable:
    if cond1:
        if cond2:
            ret.append(expr)


[expr for i in iterable1 for j in iterable2 ]
等价于
ret = []
for i in iterable1:
    for j in iterable2:
        ret.append(expr)



列表解析式使用时间:
%%timeit
x = []
for i in range(10):
    x.append(i+1)
1.39 µs ± 35 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

取奇数的列表解析式一:
x = []
for i in range(10):
    if i % 2 == 0:
        x.append(i+1)
x
[1, 3, 5, 7, 9]


条件判断复杂表达式:
x = []
for i in range(10):
    if i % 2 == 0:
        x.append(i+1)
    else:
        x.append(i+10)
x
[1, 11, 3, 13, 5, 15, 7, 17, 9, 19]
# 列表解析式
print([(i+1)**2 for i in range(10)])

列表解析式使用时间:
%%timeit
[i+1 for i in range(10)]
1.04 µs ± 37 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

取奇数的列表解析式二:
[i+1 for i in range(10) if i % 2 == 0]
[1, 3, 5, 7, 9]

 
image-20210915010504076

 
image-20210915093653422
4.1.1、条件判断简单表达式:
1.1、条件判断简单表达式:
[(i,j) for i in range(7) if i>5 for j in range(20,25)]
[(6, 20), (6, 21), (6, 22), (6, 23), (6, 24)]

[(i,j) for i in range(7) if i>5 for j in range(20,25) if j>23]
[(6, 24)]
4.1.1.1、三种判断相同
1.1.1、三种判断相同
[(i,j) for i in range(7) if i>5 for j in range(20,25) if j>23]  --->执行效率高
[(6, 24)]
[(i,j) for i in range(7) for j in range(20,25) if i>5  if j>23]
[(6, 24)]
[(i,j) for i in range(7) for j in range(20,25) if i>5 and j>23]
[(6, 24)]
4.1.1.2、生成器对象(generator)
1.1.2、生成器对象(generator)
g = (i+1 for i in range(10))    ----->生成器表达式
type(g),g
(generator, <generator object <genexpr> at 0x00000124A7024D48>)

g = (i+1 for i in range(10))
print(g)
print(next(g))
print(next(g))
print(next(g))     #迭代器,迭代器可以使用next函数驱动,迭代器都是懒惰的
<generator object <genexpr> at 0x00000124A704A048>
1
2
3

g = (i+1 for i in range(6))  #惰性的生成器对象
print(g)     #说明生成器对象就是迭代器,它是特殊构造得到的迭代器,那么它支持next
print(next(g))
print(next(g))
print(next(g))
print('-----------------------')
for i in g: 
    print(i)
print('-----------------------')
g = (i+1 for i in range(6))
for i in x:  #指针走到头了,还能再来一次吗? 不可以
    print(i)
<generator object <genexpr> at 0x00000124A701FAC8>
1
2
3
-----------------------
4
5
6  
4.1.1.3、列表是可迭代对象
1.1.3、列表是可迭代对象
x = [i+1 for i in range(5)]  #
#print(next(x)) #迭代器,列表是可迭代对象,但不是迭代器,迭代器可以使用next函数驱动,迭代器都是懒惰的
for i in x:
    print(i)
print('------------------')
for i in x:
    print(i)
1
2
3
4
5
------------------
1
2
3
4
5
    
4.1.1.4、生成器与迭代器对比
1.1.4、生成器与迭代器对比 
x = (i+1 for i in range(10))         x = (i+1 for i in range(10))
print(next(x))
for i in x:                          for i in x: 
    print(i)                            print(i)
print('-' * 30)                      print('-' * 30) 
for i in x:                          for i in x:
    print(i)                            print(i)
    
生成器表达式                          列表解析式
延迟计算                              立即计算
返回可迭代对象迭代器,可以迭代         返回可迭代对象列表,不是迭代器
只能迭代一次                          可反复迭代
4.1.2、生成器表达式和列表解析式对比
计算方式
    生成器表达式延迟计算,列表解析式立即计算
    
内存占用
    单从返回值本身来说,生成器表达式省内存,列表解析式返回新的列表
    生成器没有数据,内存占用极少,但是使用的时候,虽然一个个返回数据,但是合起来占用
    的内存也差不多
    列表解析式构造新的列表需要立即占用掉内存
    
计算速度
    单看计算时间看,生成器表达式耗时非常短,列表解析式耗时长
    但生成器本身并没有返回任何值,只返回了一个生成器对象
    列表解析式构造并返回了一个新的列表
4.2、集合解析式
语法
    {返回值 for 元素 in 可迭代对象 if 条件}
    列表解析式的中括号换成大括号{}就变成了集合解析式
    立即返回一个集合
{(x, x+1) for x in range(10)}
{[x] for x in range(10)} # 可以吗?


1.1、集合解析式
{i+1 for i in range(10)}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
4.3、字典解析式
4.3.1、简介
语法
    {key:value for 元素 in 可迭代对象 if 条件}
    列表解析式的中括号换成大括号{},元素的构造使用key:value形式
    立即返回一个字典
    
{x:(x,x+1) for x in range(10)}
{x:[x,x+1] for x in range(10)}
{(x,):[x,x+1] for x in range(10)}
{[x]:[x,x+1] for x in range(10)} #
{str(x):y for x in range(3) for y in range(4)} # 输出多少个元素?
4.3.2、字典形式
1.1.1、字典形式
{(i,i+1) for i in range(6)}
{(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)}

{i:i for i in range(0x31,0x3a)}       
{49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57}

{str(i):i+1 for i in range(1,10)}
{'1': 2, '2': 3, '3': 4, '4': 5, '5': 6}

{str(i):j for i in range(6) for j in range(5)}
{'0': 4, '1': 4, '2': 4, '3': 4, '4': 4, '5': 4}

{str(i%3):i for i in range(100)}
{'0': 99, '1': 97, '2': 98}
4.3.3、总结
Python2 引入列表解析式
Python2.4 引入生成器表达式
Python3 引入集合、字典解析式,并迁移到了2.7
一般来说,应该多应用解析式,简短、高效。如果一个解析式非常复杂,难以读懂,要考虑拆解成for循环。
生成器和迭代器是不同的对象,但都是可迭代对象。
如果不需要立即获得所有可迭代对象的元素,在Python 3中,推荐使用惰性求值的迭代器。
内建函数	函数签名	说明
sorted	sorted(iterable[, key][, reverse])	默认升序,对可迭代对象排序立即返回列表
4.3.4、sorted排序
sorted(可迭代对象,reverse=True, key=函数) #立即返回
# 排序一定是容器内全体参与
print(sorted([1,2,3,4,5]))
print(sorted(range(10, 20), reverse=True))
print(sorted({'a':100, 'b':'abc'}))
print(sorted({'a':100, 'b':'abc'}.items()))
print(sorted({'a':'ABC', 'b':'abc'}.values(), key=str, reverse=True))


排序
升序排列
sorted([1,2,3,4,5])
[1, 2, 3, 4, 5]

sorted(range(5))
[0, 1, 2, 3, 4]

sorted({'a':100,'b':50}.items(),key=lambda item: item[1])
[('b', 50), ('a', 100)]

降序排列
sorted(range(10, 20), reverse=True)
[19, 18, 17, 16, 15, 14, 13, 12, 11, 10]

转成字符串排序
sorted([1,2,3,4,'a'],key=str)
[1, 2, 3, 4, 'a']

字典取键keys
sorted({'a':100,'b':50})
['a', 'b']

生成二元组
sorted({'a':100,'b':50}.items())
[('a', 100), ('b', 50)]


标签:03,set,字节,python,image,d6,range,print,100
From: https://www.cnblogs.com/zikang/p/17103896.html

相关文章