Rethink Python 之二:序列类型
Python自带的序列类型可以分为两类:
1. 容器序列:容器序列可以存储不同类型的元素,像 list,tuple,collections.deque
2. 扁平序列:扁平序列里只能存储同一类型的元素,像str,bytes,bytearray,memoryview,array.array
容器序列里存储的是对象的引用,而扁平序列里存储的是值,而不是引用。扁平序列只能存储数字,字符这样的基本类型。
序列还有一种分法就是可变和不可变:
1. 可变类型 list,bytearray,array.array,collections.deque,memoryview
2. 不可变类型 tuple,str,bytes
上图可以让我们对python的序列提供的功能有个了解。
列表推导
tshirts=[(color,size)
for color in colors
for size in sizes
if(not(color=='black' and size=='L'))
]
# [('black', 'S'), ('black', 'M'), ('white', 'S'), ('white', 'M'), ('white', 'L')]
上边的代码生成了一个tuple的list。这个list里表示的演示是黑和白,大小是S,M,L的T恤。但是不包括黑色大号的T恤。
可以看到列表推导还是很方便的。但是它只能生成列表。为了生成其他序列,我们用生成器表达式。
生成器表达式
当然,你可以用列表推导生成一个列表,然后用这个列表去创建一个tuple,就像这样:
t = tuple([x for x in range(10)])
这个过程会先生成一个list,然后用这个list对象构造tuple。这样有个创建list的中间过程。而生成器表达式可以省去这个中间过程。它会以迭代的方式依次产生符合要求的元素。避免了内存的浪费。而生成器表达式的定义也很简单,就是把列表推导的[ ]变成( ).
t = tuple((x for x in range(10)))
array.array("I",(x for x in range(10)))
Tuple
Tuple 和 List的区别是Tuple不可变,一旦定义,元素的个数,位置,内容都不能被修改。它的这种特性可以给我们带来其他好处。比如我们要存储一个二维坐标信息,一个人的信息。
point = (2,4) # x轴,y轴
person = ('Mark',23,175,80) #姓名,年龄,身高,体重
由于元组的不可变性,用它来存储记录很合适。它的固定位置存放固定的信息。为了方便我们取出信息,tuple还有拆包的功能:
name,age,height,weight = person
可以一次从tuple里取出所有元素并赋值给变量。如果对于其中有些变量你并不感兴趣,可以用下划线来做一个通配符。但是下划线的个数要和tuple里的元素一一对应。
name,_,_,weight = person
只关心姓名和体重。
如果tuple元素很多,你不想用下划线一一匹配,你可以用星号来匹配其他元素:
name,*others,weight = person
print(others) # (23,175)
需要注意的是上边的others是一个元组。
NamedTuple
具名元组让元组在存储记录的功能上更近了一步。它有两个好处:
1. 它让元组每个元素有了名字。可以通过名字来获取元组中特定元素。
2. 它比普通对象省内存。因为它的字段名存在类里,一个具名元组内存占用和普通元组是一样的。
Person = collections.namedtuple("Person","name age height weight")
p = Person('Mark',23,180,89)
print(p) # Person(name='Mark', age=23, height=180, weight=89)
print(p.name) # Mark
切片
一个切片的完整形式是seq[start:end:step],表示对于一个序列,从start开始(包含),end结束(不包含),以step间隔取值,生成新的序列。start省略表示从0开始,end省略表示到结尾。step省略表示步长为1。也可以取负值,负值表示从右向左。
seq = [x for x in range(10)]
seq[2:9:2] #[2, 4, 6, 8]
seq[::2] #[0, 2, 4, 6, 8]
seq[::-1] #[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
你需要知道的是seq[::-1]其实是seq[slice(None,None,-1)]的简写形式。
s = slice(None,None,-1)
seq[s] #[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
对切片进行修改
如果序列是可以修改的。那么我们可以通过切边来修改序列。
seq = [x for x in range(10)]
del seq[2:4]
seq[2:5]=[1,2,3,4,5]
t = tuple((x for x in range(10)]))
提示SyntaxError: invalid syntax
多写了个], 已经修改了,谢谢提醒。
tshirts=[(color,size)
for color in colors
for size in sizes
if(not(color==’black’ and size==’L’))
]
提示NameError: name ‘colors’ is not defined