在此记录与 Python 相关的乱七八糟的东西。
神奇的 property
在 Python 中绑定属性时,如果直接把属性暴露出去,虽然写起来很简单,但是没办法检查参数;通过 property 即可以将一个函数作为属性,并在函数中对参数的值进行检查。
例如,一个学生的成绩必须在 [0, 100] 这个区间才可以,那么我们就可以使用 property 。
如上,只需要函数添加 @property 修饰符即可;此时,又会创建另外一个修饰符 @score.setter,用于把一个 setter 方法变成属性赋值;如果没有使用 setter,那么该属性为只读。
当然,也可以通过如下方式设置,两者的作用相同。
with 语句
通常会有一些任务,开始需要进行设置,处理任务,事后做清理工作。对于这种场景,Python 的 with 语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。
正常的处理过程以及使用 with 时的处理过程如下:
基本思想是 with 之后的函数返回的对象必须有 __enter__() 和 __exit__() 方法。
紧跟 with 后面的语句被求值后,返回对象的 __enter__() 被调用,这个方法的返回值将被赋值给 as 后面的变量;当 with 后面的代码块全部被执行完之后,将调用前面返回对象的 __exit__() 。
执行的顺序为 A) get_sample(); 返回 Sample 对象; B) Sample:__enter__(); 将返回的值赋值给 sample; C) 执行代码块; D) 执行 Sample:__exit__() 。
with 真正强大之处是它可以处理异常。__exit__() 有三个参数,val, type 和 trace,这些参数在异常处理中相当有用。
在 with 后面的代码块抛出任何异常时,__exit__() 方法被执行。正如例子所示,异常抛出时,与之关联的 type,value 和 stack trace 传给 __exit__() 方法,因此抛出的 ZeroDivisionError 异常被打印出来了。
循环缓冲区
Python 中可以很简单的实现一个固定长度的缓冲区,也就是固定长度的 FIFO 队列。
可以通过如下方式使用。
另外,实际上可以通过 pop() 和 insert(0, x) 将缓冲区正向输入,如上述的顺序刚好相反。
二进制文件操作
对于二进制文件,可以使用 struct 模块中的 pack、unpack 函数进行读写操作;当然对于单个 Byte 可以通过 ord()、hex() 等函数执行。
通过 struct 模块写入时,保存的时 struct 转换后的格式;如果要原生写入,可以通过如下的方式写入。
其中 struct 模块是基于 C 语言编写的库,可以参考官方文档 struct — Interpret strings as packed binary data 。
其它
首行
可以使用 #!/usr/bin/python 或者 #!/usr/bin/env python ,env 可以通过指定的环境变量执行命令。
使用 UTF-8
对于非英文的编码可以使用如下的方法之一。
带 * 参数
在 python 函数参数中,星号的作用是:*)传入任意长度的元组;**)传入任意长度的字典。如果两者之前有固定的参数列表,则先填充前面的参数。
列表推导
列表推导的格式为 [ expression for variables in list [if condition]],推导的变量可以有一个或者多个,如果是多个通常为笛卡尔乘积。
三元运算
在 Python 中 0、’‘、[]、()、{}、None 都为假,而且对于 and 如果所有值为真则会返回最后一个值,否则返回第一个假值;对于 or 如果有一个值为真则返回,否则返回最后一个值。
对于三元运算,如取最小值 small = x if x < y else y。也可以使用 and-or ,如 (1 and [a] or [b])[0],使用列表是为了防止 a 为假。
join()格式输出
生成一串数字,中间用逗号分割,其中 range 可以用 xrange 替换。
None 判断
通常的判断方式可能会有多种,不过可能在使用时有很多的问题,列举如下。
if x is None / x==None
(ob1 is ob2) 等价于 (id(ob1) == id(ob2)),也即当比较相同的对象实例,is 总是返回 True,而 == 最终取决于 “eq()”。
if not x
需要注意此时无法区分 x==[] 和 x==None,在 Python 中,None、False、空字符串”“、0、空列表[]、空字典{}、空元组() 都相当于 False。
if not x is None
实际为 if not (x is None),最好使用 if x is not None 。
os._exit()/sys.exit()
Python 程序有两中退出方式:
-
os._exit() 会直接将程序终止,之后的所有代码都不会继续执行;
-
sys.exit() 会引发一个 SystemExit 异常,如果这个异常没有被捕获,那么 python 解释器将会退出,如果有捕获此异常的代码,那么这些代码还是会执行。
内置函数 map()、filter()、reduce()
这三个函数比较类似,都是应用于序列 (list, tuple, str等) 的内置函数。
map(function, sequence[, sequence, …]) return: list
对 sequence 中的 item 依次执行 function(item),执行结果输出为 list。如果长度不同,则以最长为准,最短以 None 补齐。
reduce(function, sequence[, initial]) return: value
对 sequence 中的 item 顺序迭代调用 function,必须要有 2 个参数。如果有第 3 个参数,则表示初始值。需要注意的是,function 不能为 None 。
filter(function or None, sequence) return list, tuple, or string
对 sequence 中的 item 依次执行 function(item),将执行结果为 True 的 item 组成 list、string、tuple,这取决于 sequence 的类型。
以下为部分示例。
lambda 函数
快速定义单行的最小函数,类似于内联函数,不允许使用if函数。
processFunc 会根据 collapse 输出 “this is a test” 或者”this is\na\ttest” 。
字符串
在 Python 中,字符串不以 NULL 结尾,内部表示时会指定字符串的长度,而且一个字符串中可以有多个 NULL 字符。
前缀 r R
在 Python 的 string 前面加上 'r', 是为了告诉编译器这个 string 是个 raw string,不要转义 '\' 。 例如,\n 在 raw string 中,是两个字符,\ 和 n, 而不会转意为换行符。由于正则表达式和 \ 会有冲突,因此,当一个字符串使用了正则表达式后,最好在前面加上 'r' 。
前缀 u U
以 u 或 U 开头的字符串表示 unicode 字符串。