如何优雅地使用 Python
记录一些经常用到的 Python 技巧和方法。
基础
变量是将名字和对象关联起来,变量名是对象的引用而不是对象本身。
- 可变对象 的内存地址可以改变,也可以修改当前指向的对象的值,例如列表、字典和集合等;
- 不可变对象 的内存地址永远不会改变,无法修改其值,例如整数、浮点数和字符串等。
1 | a, b = [0] * 10, [{}] * 10 # 生成内容的地址均相同 |
数值类型和字符串类型的基础运算
1 | 0x(1), 0o(1), 0b(1) # 十六进制,八进制和二进制的字面量 |
关于列表和迭代器
1 | a = [True, False] |
集合的元素和字典的键必须是不可变对象。
1 | a.issubset(b); a<b; # 判断 a 是否是 b 的子集 |
函数的参数调用分成位置参数、关键字参数、带默认值参数、可变数量参数四种。
1 | # 函数的默认参数值在函数对象被创建时计算一次 |
lambda 函数会 绑定全局变量地址而非其值。以下代码的解决方案 见此。
1 | funcs = [] |
类
除了最常规的实例方法外,python 还有用 @staticmethod
修饰的静态方法和 @classmethod
修饰的类方法。实例方法依赖实例 self,类方法依赖类 cls 或实例 self,静态方法不依赖类和实例。
1 | class Example: |
类的继承用 class B(A)
,如果想定义抽象类则需引入 abc 库。
1 | from abc import ABC, abstractmethod |
Python 的类不存在严格意义上的私有成员,保护成员和私有成员常用 _
和 __
作为前缀。
1 | class Example: |
其中,__xxx__
是系统定义的特殊的类方法。
类或函数的方法 | 效果 |
---|---|
dir() |
类或对象的所有属性和方法(列表形式) |
__dict__ |
类或对象中的所有属性和值(字典形式) |
__doc__ |
描述信息,即定义开头长注释里的字符串;可用于模块、函数、类。 |
__new__ ,__init__ |
前者用于类对象的创建(静态方法),后者用于对象的初始化(实例方法)。前者必须要给出返回值(对象),作为后者的第一个参数。 |
__del__ |
类的析构函数 |
__module__ ,__class__ |
前者表示对象所在模块,后者表示对象所属的类 |
__str__ |
类需要转为字符串时(比如打印该对象)触发 |
__call__ |
当对象后面接 () 后会触发 |
__getitem__ |
当对象后面接 [] 后会触发 |
__setitem__ ,__delitem__ |
连同上面的 __getitem__ ,使类像字典一样使用 |
__iter__ , __next__ |
使该类变得可迭代,可以用 for ... in ... 遍历 |
标准库
argparse 参数解析
1 | import argparse |
collections 拓展数据结构
1 | ''' |
functools 高阶函数
1 | import functools |
itertools 实用的枚举方法
itertools 的所有方法都实现了生成器函数,高效而节省内存。
1 | from itertools import permutations, combinations, product |
json & pickle 序列化和反序列化
json 兼容标准的 JavaScript Object Notation 协议。
1 | json.load(open('demo.json','r')) |
pickle 是 Python 专有基于二进制的序列化和反序列化。对不信任的数据进行 unpickling 是不安全的。
1 | pickle.load(open('a.txt', 'rb')) |
random 随机
1 | from random import * |
re 正则表达式
1 | import re |
第三方库
pyparsing 定制解析器
tesserocr & pytesseract 图片文本检测
对给定图片进行文本检测,并返回识别后的字符串。
注意不太适合很小的图(比如只包括一个字符),进行适当的缩放和重复会有更好的识别效果。
Sympy 数学表达式运算
1 | x = sympy.Symbol('x') # 定义一个量 x |
Jupyter Notebook
即写即用,一直缓存结果,适合 python 开发。更推荐结合 VSCode。
在 notebook 里展示图片:
- 用
cv2.imshow("WindowsName", a)
无法正常显示图片,需要再后面加cv2.waitKey(delay)
,如delay=0
则跳出一张图片(鼠标关闭后才会继续运行)。 - 用
plt.imshow(a)
可以画出a
,但是会在代码运行完后再画。 - 用
plt.imshow(a); plt.show()
后可以立即输出图片(也可以连续画出多张图片)。
Numpy 专题
numpy 数组的几种初始化方法
1 | a = np.array([(1,2,3), (4,5,6)]) |
numpy 数组索引可以用 :
和 ,
分隔,...
表示这一维度不要求。索引还可以是数组下标、布尔和表达式。
1 | a = np.array([[1,2,3],[3,4,5],[4,5,6]]) |
numpy 的数组操作
1 | np.concatenate((a, b,...), axis = 0) # 按第 0 维连接(其他维必须一样) |
numpy 的常用函数
1 | np.random.choice(a, size, replace, p) # 随机取 a 中 size 个, replace 表示是否放回 |
numpy 的数学运算
1 | np.sin()/cos()/tan()/log()/exp() # 均可套 ndarray |
numpy 的 IO 操作
1 | ny.save(file, a, allow_pickle=True) # 将 a 保存至二进制文件(后缀名为 npy) |