流畅的Python,第二章总结

流畅的Python

第二章总结:

  1. 序列分类:
  • 容器序列(可包含任意类型对象的引用):list,tuple,collections.deque。
  • 扁平序列(只能包含一种类型且为原子类型):str,bytes,bytearray,memoryview,array.array。
    还可以按能否被修改分类:
  • 可变序列:list,bytearray,array.array,collections.deque,memoryview。
  • 不可变序列:tuple,str,bytes。
  1. 列表推导:

symbols = '!@#$%
codes = [ord(symbol) for symbol in symbols]
ord()返回Unicode码数值,python代码会忽略代码里[ ],{ },()中的换行。
列表推导还可以进行筛选,如:
codes = [ord(symbol) for symbol in symbols if ord(s) > 127]
该代码创建一个Unicode码大于127的列表。
也可以创建二维的列表:
colors = ['white', 'black', 'red']
sizes = ['S', 'M', 'L']
shirts = [(color, size) for color in colors for size in sizes]

  1. 生成器表达式:

元组初始化:
symbols = '!@#$%'
a = tuple(ord(symbol) for symbol in symbols)
若生成器表达式是一个函数调用过程中唯一一个参数,则可以省略括号。
创建数组:
import array
b = array.array('I', (ord(symbol) for symbol in symbols))
第一个参数指定了数组中数字的存储方式(如无符号整数)。

  1. 元组:

元组拆包:
city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014)
里面的元素分别赋给变量。
passport = ('USA', '31195855')
print('%s/%s' % passport)
会输出:
USA/31195855
还可以用*运算符把一个可迭代对象拆开为函数的参数:
>>>divmod(20, 8)
(2, 4)
>>>t = (20, 8)
>>>divmod(*t)
(2, 4)
divmod(a, b)返回一个元组(a/b, a%b)
>>>import os
>>>_, filename = os.path.split('/home/luciano/.ssh/idrsa.pub')
>>>filename
'idrsa.pub'
os.path.split()返回以路径和最后一个文件名组成的元组(path, last_part),
通常使用_占位符处理不感兴趣的数据。
使用 *args来获取不确定数量的参数:

>>>a, b, *rest = range(5)
>>>a, b, rest
(0, 1, [2, 3, 4])
>>>a, b, *rest = range(3)
>>>a, b, rest
(0, 1, [2])
>>>a, b, *rest = range(2)
>>>a, b, rest
(0, 1, [])

这个变量可以放在任意位置:

>>> a, *body, c, d = range(5)
>>> a, body, c, d
(0, [1, 2], 3, 4)
>>> *head, b, c, d = range(5)
>>> head, b, c, d
([0, 1], 2, 3, 4)
  1. 切片:
>>> s[::3]
'bye'
>>> s[::-1]
'elcycib'
>>> s[::-2]
'eccb'

给切片赋值:

>>> l = list(range(10))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l[2:5] = [20, 30]
>>> l
[0, 1, 20, 30, 5, 6, 7, 8, 9]
>>> del l[5:7]
>>> l
[0, 1, 20, 30, 5, 8, 9]
>>> l[2:5] = 100
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    l[2:5] = 100
TypeError: can only assign an iterable
>>> l[2:5] = [100]
>>> l
[0, 1, 100, 8, 9]

报错是因为赋值语句右边得是可迭代对象。

  1. 建立由列表组成的列表:
>>> board = [['_']*3 for i in range(3)]
>>> board
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
>>> board[1][2] = 'x'
>>> board
[['_', '_', '_'], ['_', '_', 'x'], ['_', '_', '_']]

下面这种方法看似很正常,却是错误的:

>>> board = [['_']*3]*3
>>> board
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
>>> board[1][2] = 'x'
>>> board
[['_', '_', 'x'], ['_', '_', 'x'], ['_', '_', 'x']]

因为里面的3个列表其实是对同一对象的引用。

  1. 序列的增量赋值:

+=的特殊方法为__iadd__,=的特殊方法为__imul__。
对于可变对象,使用+=和
=不会创建新的对象,而是在原来的对象追加新元素,对于不可变对象,+=会报错,*=会创建新的对象,把原来的对象复制到新的对象,再在新的对象追加新元素。

一个意外的结果:

>>> t = (1, 2, [30, 40])
>>> t[2] = 4
Traceback (most recent call last):
  File "<pyshell#51>", line 1, in <module>
    t[2] = 4
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2, [30, 40])
>>> t[2] += [12]
Traceback (most recent call last):
  File "<pyshell#53>", line 1, in <module>
    t[2] += [12]
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2, [30, 40, 12])

所以不要把可变对象放在元组里。

  1. list.sort和list.sorted

sort不会创建新的对象,而是对原来的对象就地改动,返回None;sorted会创建一个新的对象,返回一个列表。
两个函数都有两个参数:reverse和key。
reverse若为True,则降序,默认为False;
key为对比关键字,如key=len,则进行基于字符串长度的排序,key = str.lower可以忽略大小写的排序,默认为按照Unicode码的大小排序。

  1. 用bisect来搜索
import bisect          
print(dir(bisect))
a = [3, 4, 234, 324, 234]
a.sort()
b = bisect.insort(a, 3)         #这个函数就是插入一个数并返回该数插入的位置
b = bisect.bisect(a, 3)            #不插入这个数但返回这个数应该插的位置 
b = bisect.bisect_left(a, 3)        #当插入重复的数时,就取列表数的左边
  1. 数组:

存放数字时,数组的效率要比列表高,因为数组背后存放的并不是数字类型(如float类型),而是字节表述,如同c中的数组。

>>> from array import array
>>> from random import random
>>> floats = array('d', (random() for i in range(10**7)))

创建10^7个浮点数,第一个参数为类型码,指定在底层C中应该存放怎样的数据结构。

float.tofile(fp)可以数组写入文件,速度很快。
float.from(fp,10**7)同样可以从文件中读取数组。

  1. NumPy:
>>> import numpy
>>> a = numpy.arange(12)
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
>>> type(a)
<class 'numpy.ndarray'>
>>> a.shape
(12,)
>>> a.shape = 3, 4  #变成3行4列,即一个二维数组
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a[2]
array([ 8,  9, 10, 11])
>>> a[2,1]
9
>>> a[:,1]
array([1, 5, 9])
>>> a.transpose()			#行列互换
array([[ 0,  4,  8],
       [ 1,  5,  9],
       [ 2,  6, 10],
       [ 3,  7, 11]])
  1. collections.deque

利用.append和.pop方法,我们可以把列表当作栈和队列,但是很耗时。
collections.deque是一个双向队列的类,可快速从两端增加和删除元素。

>>> from collections import deque
>>> dq = deque(range(10), maxlen = 10)		#指定这个队列的大小
>>> dq
deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.rotate(3)#给出一个参数n,若n>0,则最右边n个元素会移动最左边
>>> dq
deque([7, 8, 9, 0, 1, 2, 3, 4, 5, 6], maxlen=10)
>>> dq.rotate(-4)#若n<0,则最左边的n个元素会移动到最右边
>>> dq
deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 0], maxlen=10)
>>> dq.appendleft(-1)#在左边添加一个元素,若队列已满,则最右边的元素被删除
>>> dq
deque([-1, 1, 2, 3, 4, 5, 6, 7, 8, 9], maxlen=10)
>>> dq.extend([11, 22, 33])#同上
>>> dq
deque([3, 4, 5, 6, 7, 8, 9, 11, 22, 33], maxlen=10)
>>> dq.extendleft([10, 20, 30, 40])
>>> dq
deque([40, 30, 20, 10, 3, 4, 5, 6, 7, 8], maxlen=10)

猜你喜欢

转载自blog.csdn.net/tlssnp/article/details/114264623