第1章 用Pythonic方式来思考

第1条

pass

第2条:遵循PEP8风格指南

  • 使用space(空格)来表示缩进,而不要用tab
  • 和语法相关的每一层都用4个空格来表示
  • 每行的字符数不超过79
  • 受保护的实例属性,应该以单个下划线开头
  • 私有的实例属性,应该以两个下划线开头
  • 类与异常,应该以每个单词首字母均大写的形式来命名
  • 模块级别的常量,应该全部采用大写字母来拼写,各单词之间以下划线相连
  • if a is not b 而不是 if not a is b
  • 不要通过检测长度的方法(if len(somelist) == 0)来判断somelist是否为空,而是采用if not somelist来判断。

第3条:了解bytes, str 与unicode的区别

bytes是给计算机看的,str和unicode是给人看的。


  • Python3字符序列的两种表示为byte和str。前者的实例包含原始的8位值,即原始的字节;后者的实例包括Unicode字符。
  • 要想把Unicode字符转换为二进制数据,就必须使用encode方法。要想把二进制数据转换成Unicode字符,则必须使用decode方法。
  • 在Python3中,bytes是一种包含8位值的序列,str是一种包含Unicode字符的序列。开发者不用比较操作来混合处理。
def to_str(bytes_or_str):
	if isinstance(bytes_or_str, bytes):
		return bytes_or_str.decode('utf-8')
	else:
		return bytes_or_str

def to_bytes(bytes_or_str):
	if isinstance(bytes_or_str, bytes):
		return bytes_or_str.encode('utf-8')
	else:
		return bytes_or_str

第4条:用辅助函数来取代复杂的表达式

pass

第5条:了解切割序列的办法

  • 切片操作不会计较start和end索引是否越界。如果越界,则去边界值,而不会取越界值。

第6条:在单词切片操作内,不要同时指定start,end和stride

步进式切片:somelist[start : end : stride]

a = [1, 2, 3, 4, 5, 6]
# 取奇数
odds = a[::2]
#取偶数
evens = a[1::2]

传入stride = -1,能够把字节形式存储的字符串反转过来。

x = b'mongoose'
y = x[::-1]

这种技巧对字节串和ASCII字符有用,但是对已经编码成UTF-8字节串的Unicode字符无效。

w = '谢谢'
x = w.encode('utf-8')
y = x[::-1]
z = y.decode('utf-8')
>> z = y.decode('utf-8')  UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa2 in position 0: invalid start byte

为了让代码便于阅读,不要同时把start,end, stride同时写在一起。使用步进式切片,把切割结果赋值给某个变量,然后再进行二次切割

a = ['a','b','c','d','e','f','g','h']
b = a[::2] # ['a','c','e','g']
c = b[1:-1] # ['c','e']

如果程序对执行时间或内存用量要求非常严格,以致不能采用两阶段切割法,可以考虑考虑使用Python 内置的itertools模块,该模块中有个islide方法,这个方法不允许为start, end或stride指定负值。(第46条)、

第7条:用列表推导来取代map和filter

列表推导:根据一份列表来制作另外一份

用列表推导式来写代码,会更简洁,不过根据正月点灯笼的讲解,使用map运行会更块,在数据量非常巨大的时候有着量级的优势。

代码:
构建一个列表的元素平方列表

a = [1,  2,  3,  4,  5,  6,  7,  8,  9, 10]
# 列表推导式
squares = [x**2 for x in a]

# map方法
squares = map(lambda x: x ** 2, a)

如果外加一个限制条件,比如说元素能被2整除才会进行平方操作:

# 列表推导式
even_squares = [x ** 2 for x in a if x % 2 == 0]

# map方法与filter的结合
alt = map(lambda x: x**2, filter(lambda x: 2 % 2 == 0, a))
assert even_squares == list(alt)

第8条:不要使用含有两个以上表达式的列表推导

两层列表推导。这个功能采用包含两个for表达式的列表推导即可实现,这些for表达式会按照从左至右的顺序来评估。

matrix = [[1,2,3],[4,5,6],[7,8,9]]
flat = [x for row in matrix for x in row]
>>> [1,2,3,4,5,6,7,8,9]

对二维矩阵中的每个单元格取平方,然后用这些平方值构建新矩阵。

squared = [[x**2 for x in row] for row in matrix]
>>>[[1, 4, 9], [16, 25, 36], [49, 64, 81]]

列表推导也支持多个if条件。

a = [1,2,3,4,5,6,7,8,9,10]
b = [x for x in a if x > 4 if x % 2 == 0]
c = [x for x in a if x > 4 and x % 2 == 0]

第9条:用生成器表达式来改写数据量较大的列表推导

列表推导式缺点:当数据非常多的时候,会消耗大量的内存。

生成器:是对列表推导和生成器的一种泛化。生成器表达式在运行的时候,并不会把整个输出序列都呈现出来,这个迭代器每次可以根据生成器表达式产生一项数据。

# 列表推导式:
value = [len(x) for x in open('/tmp/my_file.txt')]
print(value)
>>> [100, 57, 15, 1, 12, 75, 5, 86, 89, 11]
# 生成器表达式:
value = (len(x) for x in open('/tmp/my_file.txt'))
print(value)
>>> <generator object <genexpr> at 0x101b81480>

生成器调用next方法就可以输出下一个值。

套娃生成器:让生成器相互结合。把一个生成器 表达式 所返回的 迭代器 用作 另外一个 生成器表达式的输出值

it = (len(x) for x in open('/tmp/my_file.txt'))
roots = ((x, x**0.5) for x in it)

第10条:尽量用enumerate 取代range

enumerate可以把各种迭代器包装成生成器。每次产生一对值,第一个值为循环下标,第二个为从迭代器中获取到的下一序列元素

for i, flavor in enumerate(flavor_list):
	print('%d: %s' % (i, flavor))
>>>
>0: vanilla
>1:chocolate
>2:pecan
>3:strawberry

指定计数的起始值

for i, flavor in enumerate(flavor_list, 3):
	print('%d: %s' % (i, flavor))
>>>
>3: vanilla
>4:chocolate
>5:pecan
>6:strawberry

第11条:用zip函数同时遍历两个迭代器

Python3中的zip函数,可以把两个或两个以上的迭代器封装为生成器。这种zip生成器,会从每个迭代器中获取迭代器的下一值,然后把这些值汇聚成元组。

需要注意zip的多个迭代器的长度是否统一。

不要在for和while循环后面写else块

for i in range(3):
	print(i)
else:
	print("else block")
>>>
0
1
2
else block

含义:循环里用break语句提前跳出,会导致程序不执行else块。

对比

for i in range(3):
	print(i)
	if i == 1:
		break
else:
	print("else block")
>>>
0
1

总结:不要在for和while循环后面写else块

第13条:合理利用try/except/else/finally结构中的每一个代码块

1.finally块

try – finally模块。执行try后,总是执行finally块。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值