Reading Notes - Effective Python (Second Edition)
# Pythonic 思维
Python 社区用 Pythonic 来形容具有特定 Python 风格的代码。这种风格不是严格的规范,而是大家在个人或合作使用 Python 语言的过程中逐渐形成的 good practice 经验。
# [02] 遵循 PEP 8 风格指南
请参阅 PEP 8 – Style Guide for Python Code (opens new window) 获取完整的 PEP 8 风格指南。
与空白有关的建议:
用 4 个空格 (space) 表示缩进,而不要用制表符 (tab) 。
每行不超过 79 个字符。
对于占据多行的长表达式,除首行外各行应在正常缩进基础上再加 4 个空格。
函数与类之间用两个空行隔开。
在同一个类中,方法之间用一个空行隔开。
在使用字典时,键与冒号之间不加空格,冒号与值之间用一个空格隔开。
在变量赋值时,赋值运算符的左右均用一个空格隔开。
在类型注解时,变量名与冒号之间不加空格,冒号与类型信息之间用一个空格隔开。
与命名有关的建议(类外):
命名函数、变量、属性时用下划线命名法,例如
user_name
。命名 module-level 的常量时,用下划线并且全字大写,例如
BUFFER_SIZE
。
与命名有关的建议(类内):
命名类时用帕斯卡(大驼峰)命名法,例如
LinkedList
。命名 protected 的实例属性时,用一个下划线开头,例如
_foo
。命名 private 的实例属性时,用两个下划线开头,例如
__foo
。对于实例方法,应将其第一个参数命名为
self
,表示该对象本身。对于类方法,应将其第一个参数命名为
cls
,表示该类本身。
与表达式和语句有关的建议:
行内否定:使用
if a is not b
的形式,而不是if not a is b
的形式。容器判空:使用
if not somelist
的形式,而不是if len(somelist) == 0
的形式。类似地,使用if somelist
的形式判断容器非空。对于多行的表达式,用括号括起来,而不是用
\
续行。
与 import
有关的建议:
总是将
import
语句放在文件的最开头。总是使用绝对名称而不是相对名称(为什么?)。
将文件中的
import
语句按照顺序划分为三个部分:首先是标准库内的模块,然后是第三方模块,最后是自己的模块。
# [03] 了解 bytes 和 str 的区别
# 基本概念
bytes
对象包含的是原始二进制数据,即 8 位的无符号值序列:
a = b'h\x65llo'
print(list(a))
print(a)
[104, 101, 108, 108, 101]
b'hello'
str
对象包含的是 Unicode 字符串,与文本字符相对应:
a = 'a\u0300 propos'
print(list(a))
print(a)
['a', '`', ' ', 'p', 'r', 'o', 'p', 'o', 's']
a` propos
# 互相转换
把字符串转换成二进制数据需要用 str.encode()
方法编码,把二进制数据转换成字符串需要用 bytes.decode()
方法解码。调用编码和解码方法时,可以指定编码方案,也可以采用系统默认的方案(通常是 UTF-8)。
bytes
对象不一定非要按照某一种固定的方案解码成字符串,str
对象也不一定非要按照某一种固定的方案编码成二进制数据。
可以编写两个辅助函数以互相转换 bytes
和 str
对象:
def to_bytes(data) -> bytes:
if isinstance(data, str):
return data.encode('utf-8')
return data
def to_str(data) -> str:
if isinstance(data, bytes):
return data.decode('utf-8')
return data
# 互不兼容
bytes
和 str
类型以几乎相同的方式工作,但仅限同类型的对象,二者之间互不兼容。
# OK
a = b'foo' + b'bar'
a = 'foo' + 'bar'
assert b'red' > b'blue'
assert 'red' > 'blue'
# OK
assert b'foo' != 'foo'
# TypeError
a = b'foo' + 'bar'
a = 'foo' + b'bar'
assert b'red' > 'blue'
assert 'red' > b'blue'
# 工作方式差异
在字符串格式化时,bytes
和 str
类型的输出形式不同:
x = b'foo'
y = 'bar'
print(f'see bytes {x} and str {y}')
see bytes b'foo' and str bar
在读写文件时,读写 bytes
类型数据需要在二进制模式下进行:
x = b'foo'
with open('data.bin', 'wb') as f:
f.write(x)
y = 'bar'
with open('data.txt', 'w') as f:
f.write(y)
对于读文件,可以在字符串模式下读取二进制文件,但必须使用正确的编码格式,否则会抛出解码异常:
with open('data.bin', 'r', encoding='utf-8') as f:
z = f.read()
# [04] 使用 f-string 代替旧式格式化字符串
TBD. 将使用 f-string 的具体好处汇总到 python f-string 文章中
# [05] 用辅助函数取代复杂的表达式
TBD.
- 01
- Reading Papers - Kernel Concurrency06-01
- 02
- Linux Kernel - Source Code Overview05-01
- 03
- Linux Kernel - Per-CPU Storage05-01