首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >啃书 -- 流畅的python 第二章 丰富的序列

啃书 -- 流畅的python 第二章 丰富的序列

原创
作者头像
逸澄
发布2025-02-16 17:03:01
发布2025-02-16 17:03:01
3140
举报
文章被收录于专栏:啃书啃书

第二章 : 序列

2.1 列表推导式和生成器表达式

  1. 列表推导式用于生成列表, 即简单的 l=[_ for _ in range(0,11)] 等类似的表达。
  2. 生成器表达式可以生成其它类型的序列,比列表推导式占用的内存空间更少,因为生成器表达式使用迭代器协议逐个产出项,列表推导式是直接产生一整个list;

语法只是将[]换成()

代码语言:python
复制
colors = ['black', 'white']

sizes = ['S', 'M', 'L']



#列表推导式

tshirts\_list= [f"({color},{size})" for color in colors

                                   for size  in sizes]

#生成器推导式

tshirts\_tuple= (f"({color},{size})" for color in colors

                                    for size  in sizes)

print(tshirts\_list)

#直接打印tshirts\_tuple 

print(tshirts\_tuple)

#遍历打印tuple 

for item in tshirts\_tuple:

    print(item)

#可见生成器不会生成包含6个元素的列表,而是会一个个生成
代码语言:txt
复制
['(black,S)', '(black,M)', '(black,L)', '(white,S)', '(white,M)', '(white,L)']

<generator object <genexpr> at 0x000001AEE9649F50>

(black,S)
(black,M)
(black,L)
(white,S)
(white,M)
(white,L)

2.2 tuple 的作用

  1. 可以用作记录 :city,year = ('Tokyo',2003)
  2. 用作不可变列表 :

* tuple 如果存放可变项,那么元祖的值可能发生变化。

* tuple 存放不可变项,

代码语言:python
复制
a=(10,'a',[1,2])

b=(10,'a',[1,2]) # 注意到第3项存放的list 是可变项,因此

print(a)

#b[-1] = [2,3]   值的变化error, 因为tuple不支持赋值;

b[-1].append(99) #append 可pass

print(b)
代码语言:txt
复制
(10, 'a', [1, 2])
(10, 'a', [1, 2, 99])

2.5 序列和可迭代对象拆包

1. 拆包

1) 并行赋值

2) 值交换

3) 传参

4) 接收函数返回的多个值

5) tuple 拆包的一个强大功能:嵌套拆包 ,即(a,b,(c,d)) -> a,b,c,d for a,b,(c,d) in tuple:

代码语言:python
复制
# 拆包: 

#并行赋值、值调换

a,b = 10,15

b,a = a,b

print(a,b)
代码语言:python
复制
#传参

t=(10,20)

quotient,remainder = divmod(*t) # 若去掉* 则报错: 函数需要2个参数但只传了一个参数

print(f"{quotient} {remainder}")
代码语言:python
复制
#函数输出

import os

file_path = "C:/Users/AppData/Roaming/Microsoft/Windows/ppt.pptx"

_,file = os.path.split(file_path)

print(file)
代码语言:python
复制
#tuple的嵌套拆包

metro\_areas = [('Tokyo', 'JP', 36.933, (35.689722, 139.691667)), 

               ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)), 

               ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),

               ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),

               ('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)), ]

print(f'{"":15}|{"latitude":>9}|{"longititude":>10}')

for city,_,_,(latitude,longititude) in metro_areas:

    print(f"{city:>15}|{latitude:9.4f}|{longititude:9.4f}")

2. * 的作用

1) 定义函数时 : *args捕获余下的任意数量参数

2) 并行赋值: _的位置任意,但只能出现一次;在函数调用时,_ 可以出现多次

3) 在函数调用 和序列字面量中使用

代码语言:python
复制
a,b,*c = range(1,10)

print(a,b,c)

a,*b,c =  range(1,10)

print(a,b,c)
代码语言:txt
复制
1 2 [3, 4, 5, 6, 7, 8, 9]
1 [2, 3, 4, 5, 6, 7, 8] 9
(1, 2, (3, 4))
代码语言:python
复制
def func(a,b,\*c):

    return a,b,c

print(func(\*(1,2),3,4))  # \*用来指示拆包;对不不带\* 会发生什么:

print(func((1,2),3,4))
代码语言:txt
复制
(1, 2, (3, 4))
((1, 2), 3, (4,))
代码语言:python
复制
#序列字面量赋值

#tuple

a,b,c = \*range(2),3 #注意不能去掉,3 否则无法判断是否是tuple , 拆包出现语法错误

print(a,b,c)

print([\*range(4)])

print(\*range(4),4,5,\*range(6))
代码语言:txt
复制
0 1 3
[0, 1, 2, 3]
0 1 2 3 4 5 0 1 2 3 4 5

2.6 模式匹配

1) 序列 + match/case 的强大用法。 假设有以下指令:

('mpu','conv1d')

('dma','get_data',128)

('dma','send_data',256)

('vpu','eltwise')

通过match/case来开启不同模块执行指令

2) 添加类型信息可以让模式更具体:

case(str(name),_,_,(float(lat),float(lon)): 或写成 case(str(name),*_,(float(lat),float(lon)):

在模式匹配上下文,会检查这些值的类型是否符合要求;

代码语言:python
复制
def op(command):

    match command:

        case('mpu',mpu\_operate):

            print(f"mpu {mpu\_operate}")

        case('dma',dma\_op,data\_amount\_Byte):

            print(f"dma {dma\_op} {data\_amount\_Byte} Byte")

        case \_:

            raise ValueError(command)

command = ('dma','send\_data',256)

op(command)
代码语言:txt
复制
dma send\_data 256 Byte

2.7 切片

  1. list 切片 a:b:c : start:stop:step

其它:slice(a,b,c) , 返回slice 对象

通过给slice 命名可以提高程序可读性

2.8 是用* 和 + 处理序列

  1. 构建嵌套列表, 注意一下2个构建方法的区别
代码语言:python
复制
# 1. 

a = [['\_']\*3 for i in range(3)]  #创建一个list ,嵌套3个 3长度列表

print(a)

a[1][1]='x'  # 可以单独修改每一个item

print(a)

# 2. 

a=[['\_']\*3]\*3  #创建1个列表, 创建1个3长度列表并复制3份,每份指向同一个引用

print(a)

a[1][1]='x' #修改一个则其余2个都跟着改变

print(a)
代码语言:txt
复制
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

[['_', '_', '_'], ['_', 'x', '_'], ['_', '_', '_']]

[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

[['_', 'x', '_'], ['_', 'x', '_'], ['_', 'x', '_']]
  1. += 和 *= 实际调用 __iadd__ 和 __imul__ 方法, 若没有实现这两个方法,则调用__add__和__mult__ 方法

可变对象可实现就地修改;

不可变对象会先创建一个新对象,在将最终结果赋值进去。而实际实验中发现 : 不可变对象会报error ,而不是创建新的对象。

代码语言:python
复制
a=[\_ for \_ in range(4)]

print(id(a))

a+=[45]

print(a)

print(id(a)) # 同一个对象



b=(\_ for \_ in range(4))

print(id(b))

b\*=2  # 这里直接爆了Error , 而不是书中写的创建一个的b 并赋值

print(id(b))
代码语言:txt
复制
2000309021312
[0, 1, 2, 3, 45]
2000309021312
2000296589488
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[76], line 9
      7 b=(\_ for \_ in range(4))
      8 print(id(b))
----> 9 b\*=2
     10 print(id(b))
TypeError: unsupported operand type(s) for \*=: 'generator' and 'int'

2.9 list.sort 和 sorted()

  1. list.sort 就地改变原对象,不会生成新对象, 返回值为None;

不生成新对象的方法返回值为None 为python 的约定,缺点是不能嵌套调用,优点是提醒使用者该函数不会生成新对象

  1. sorted() 函数生成新的对象,因此可以操作任何可迭代对象,包括可变和不可变
  2. 这两个函数包括2个参数:

1) key : 根据什么规则排列

2) reverse: True 降序排列; False 升序排列(默认)

代码语言:python
复制
fruits= ['grape','raspberry','apple','banana']

print(sorted(fruits)) 

print(sorted(fruits,reverse=True))

print(sorted(fruits,key=len))

print(fruits)

print(fruits.sort()) # 返回值为None

print(fruits) #改变了fruits 对象
代码语言:txt
复制
['apple', 'banana', 'grape', 'raspberry']

['raspberry', 'grape', 'banana', 'apple']

['grape', 'apple', 'banana', 'raspberry']

['grape', 'raspberry', 'apple', 'banana']

None

['apple', 'banana', 'grape', 'raspberry']

2.9 其它序列

  1. array : 存放大量相同类型的数据 ,占用内存远远低于list 1) array.array('类型', value) 2) 可以写bin 文件 步骤: a. 创建并打开一个bin 文件, b. 调用 a.tofile('filename') 函数 c. 关闭文件 3) 可以读bin 文件 步骤: a. 创建一个空的 与bin文件数据类型相同的array b. 打开bin c. 调用 b.fromfile('filename', data个数) d. 关闭文件 4) 读写bin 文件比 txt 文件要快很多 5) python不允许向array 中添加与指定类型不同的值
代码语言:python
复制
from array import array
from random import random
a = array('d',(random() for i in range(2**8)))
print(a[-1])

# 写到一个二进制文件中

fp = open('data.bin','wb')

a.tofile(fp)

fp.close()



# load bin 到array 

b = array('d')

fp = open('data.bin','rb')

b.fromfile(fp,2**8) 

fp.close()

print(b[-1])
代码语言:txt
复制
0.6979163457345411
0.6979163457345411
  1. memoryview

共享内存,用来处理array 的切片,不会生成新的对象.

问题:

1) 如何生成一个mem ?

2) 如何mem 进行不同维度的变换?

代码语言:python
复制
from array import array

a = array('B',(range(0,6)))

mem1 = memoryview(a)

mem2 = mem1.cast('B',[2,3])

print(mem2.tolist())

mem3 = mem1.cast('B',[3,2])

print(mem3.tolist())

mem3[1,1]=34

mem2[0,0]=22

print(a) # 共享内存,原始的array 值会改变
代码语言:txt
复制
[[0, 1, 2], [3, 4, 5]]
[[0, 1], [2, 3], [4, 5]]
array('B', [22, 1, 2, 34, 4, 5])

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第二章 : 序列
    • 2.1 列表推导式和生成器表达式
    • 2.2 tuple 的作用
    • 2.5 序列和可迭代对象拆包
      • 1. 拆包
      • 2. * 的作用
    • 2.6 模式匹配
    • 2.7 切片
    • 2.8 是用* 和 + 处理序列
    • 2.9 list.sort 和 sorted()
    • 2.9 其它序列
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档