Python Tricks¶
Table of Contents¶
- Table of Contents
- Reference
- 变量交换
- 元素遍历
- 字符串连接
- 上下文管理器
- 使用生成式
- 使用装饰器
- 使用 collections 库
- 序列解包
- 遍历字典 key 和 value
- 链式比较操作
- if else 三目运算
- 真值判断
- for else 语句
- 字符串格式化
- 切片
- 使用生成器
- 获取字典元素的 get 方法
- 预设字典返回的默认值
- 函数参数 unpack
- 注意函数默认参数
- 为 dict 添加missing方法
- python 解释器中的 _
- Zen
- try/except/else
- print 重定向输出到文件
- 省略号
- pow 还有第三个参数
- isinstance可以接收一个元组
- 字典的无限递归
- Python可以认识Unicode中的数字
- 不能访问到的属性
- 使用计数器对象进行计数
- 漂亮的打印 JSON
- 字典的剧本
- 无限循环的结束
- 序列乘法
- here starts my collection
- 或的另一种写法
变量交换¶
python 中交换两个变量不需要引入临时变量
a = 1
b = 2
a, b = b, a
>>> a
2
>>> b
1
由此自然想到三个变量的交换 答案是也可以。
a = 1
b = 2
c = 3
a, b, c = c, a, b
>>> a
3
>>> b
1
>>> c
2
元素遍历¶
普通的遍历,类似于其他语言中的 for each 或者是基于范围的 for 循环
for i in range(5):
print(i)
带索引的容器遍历,使用 enumerate
colors = ['red', 'green', 'blue', 'yellow']
for index, color in enumerate(colors):
print('%d, %s' %(index, color))
事实上,enumerate 还接受第二个参数,用于指定 index 的起始位置,默认为 0
>>> lst = ["a", "b", "c"]
>>> list(enumerate(lst, 1))
[(1, 'a'), (2, 'b'), (3, 'c')]
字符串连接¶
names = ['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie']
print (', '.join(names))
实际上,经常使用的 字符串连接方法有三种,join format 和 + 操作符 在需要连接的字符串个数较少的情况下,+ 的效率有些许优势,随着个数的增加,join 的优势会迅速显现
上下文管理器¶
with open('data.txt') as f:
data = f.read()
使用生成式¶
最常见的是列表推导式
[2*i for i in range(10)]
其次还有:集合推导式和字典推导式,原先在 python2 版本中的 set 是需要通过 set 函数来显示转换的, 但后来 python3 中直接进行 set 推导的语法也被移植到了 python2 中。不过要注意的是 () 定义的不是元组生成式而是生成器
numbers = [1, 2, 3]
my_dict = {number: number * 2 for number in numbers if number > 1}
print(my_dict)
推导式可以嵌套,而且可以加入一定的条件机制,各个条件之间的关系是 与 。
results = [(x, y)
for x in range(10)
for y in range(10)
if x + y == 5
if x > y]
>>> results
[(3, 2), (4, 1), (5, 0)]
甚至可以利用列表生成式来实现快速排序
def quicksort(lst):
if len(lst) == 0:
return []
else:
return quicksort([x for x in lst[1:] if x < lst[0]]) + [lst[0]] + \
quicksort([x for x in lst[1:] if x >= lst[0]])
非常优美
使用装饰器¶
import urllib.request as urllib
def cache(func):
saved = {}
def wrapper(url):
if url in saved:
return saved[url]
else:
page = func(url)
saved[url] = page
return page
return wrapper
@cache
def web_lookup(url):
return urllib.urlopen(url).read()
使用 collections 库¶
deque
from collections import deque
names = deque(['raymond', 'rachel', 'matthew', 'roger',
'betty', 'melissa', 'judith', 'charlie'])
names.popleft()
names.appendleft('mark')
deque 还具有 maxlen 关键字参数,可以限制其最大容量
letters = deque(['a', 'b', 'c', 'd', 'e'], maxlen = 5)
>>> letters
>>> deque(['a', 'b', 'c', 'd', 'e'])
>>> letters.append('f')
>>> deque(['b', 'c', 'd', 'e', 'f'])
序列解包¶
p = 'vttalk', 'female', 30, 'python@qq.com'
name, gender, age, email = p
*另外可以用 name 来接收不需要的一大段值
name, *middle, email = p
>>> name
>>> 'vttalk'
>>> middle
>>> ['female', 30]
>>> email
>>> 'python@qq.com'
遍历字典 key 和 value¶
d = {'a':1, 'b':2, 'c':3}
for k, v in d.items(): # python2 有 iteritems 方法,但在 python3 中已经被移除
print (k, '--->', v)
链式比较操作¶
age = 59
if 18 < age < 60:
print('yong man')
>>> False == False == True
# 相当于 (False == False) == (False == True)
>>> False
if else 三目运算¶
text = '男' if gender == 'male' else '女'
真值判断¶
很多情况下 不需要使用 == 和 != 去比较真假
if values:
do_something()
真假值对照表
类型 | False | True :--: | :---: | :---: bool | False | True str | '' | 非空str 数值 | 0,0.0 | 非0数值 容器 | [],(),{},set() | 非空容器 None | None | 非None对象
for else 语句¶
mylist = [0, 1, 2, 3]
for i in mylist:
if i == 2:
break # 跳出整个 for else 循环
print(i)
else:
print('oh yeah')
字符串格式化¶
python3 更提倡使用 format 格式化方法,虽然很难说这样做代码量更少,但 format 确实有很多 % 格式化方法所不具有的优点
s1 = "foofish.net"
s2 = "vttalk"
s3 = "welcome to {blog} and following {wechat}".format(blog=s1, wechat=s2)
切片¶
切片操作接受三个参数,分别是起始位置,结束位置(不包括)和步长
items = list(range(10))
# 第1到第4个元素的范围区间
sub_items = items[0:4]
# 奇数
odd_items = items[1::2]
#拷贝
copy_items = items[::]
#或者
copy_items1 = items[:]
python 中常见的容器拷贝(深)就是通过切片来实现的,因为赋值操作本质上是标签(指针)的赋值
使用生成器¶
def fib(n):
a, b = 0, 1
while a < n:
yield a
a, b = b, a + b
预设字典返回的默认值¶
当 key 不存在时即返回默认值
# 第一种方式 setdefault
data = {('a', 1), ('b', 2), ('a', 3)}
groups = {}
for (key, value) in data:
groups.setdefault(key, []).append(value)
# 第二种方式 defaultdict 库
from collections import defaultdict
groups = defaultdict(list)
for (key, value) in data:
groups[key].append(value)
函数参数 unpack¶
本质上就是容器/可迭代对象的解包
def foo(x, y):
print(x, y)
alist = [1, 2]
adict = {'x': 1, 'y': 2}
foo(*alist) # 1, 2
foo(**adict) # 1, 2
注意函数默认参数¶
def foo(x=[]):
x.append(1)
print(x)
>>> foo()
[1]
>>> foo()
[1, 1]
更安全的做法
def foo(x=None):
if x is None:
x = []
x.append(1)
print(x)
>>> foo()
[1]
>>> foo()
[1, 1]
为 dict 添加missing方法¶
class Dict(dict):
def __missing__(self, key):
self[key] = []
return self[key]
>>> dct = Dict()
>>> dct["foo"].append(1)
>>> dct["foo"].append(2)
>>> dct["foo"]
[1, 2]
很像 collections.defaultdict
from collections import defaultdict
dct = defaultdict(list)
>>> dct["foo"]
[]
>>> dct["bar"].append("Hello")
>>> dct
defaultdict(<type 'list'>, {'foo': [], 'bar': ['Hello']})
Zen¶
import this
try/except/else¶
try:
put_4000000000_volts_through_it(parrot)
except Voom:
print "'E's pining!"
else:
print "This parrot is no more!"
finally:
end_sketch()
print 重定向输出到文件¶
# python3 中移除
>>> print >> open("somefile", "w+"), "Hello World"
注意打开的模式: "w+" 而不能 "w" , 当然 "a" 是可以的
pow 还有第三个参数¶
都知道 pow 是用来求幂的函数,但其实 pow 还接受第三个参数,用来求模 pow(x, y, z) == (x ** y) % z
>>> pow(4, 2, 2)
0
>>> pow(4, 2, 3)
1
isinstance可以接收一个元组¶
元组内的类型是或的关系
>>> isinstance(1, (float, int))
True
>>> isinstance(1.3, (float, int))
True
>>> isinstance("1.3", (float, int))
False
>>> isinstance("1.3", (float, int, str))
True
字典的无限递归¶
虽然没什么用,但很有意思
>>> a, b = {}, {}
>>> a['b'] = b
>>> b['a'] = a
>>> a
{'b': {'a': {...}}}
# 链表无限循环
>>> a, b = [], []
>>> a.append(b)
>>> b.append(a)
>>> a
[[[...]]]
不能访问到的属性¶
>>> class O(object):pass
...
>>> o = O()
>>> setattr(o, "can't touch this", 123)
>>> o.can't touch this
File "<stdin>", line 1
o.can't touch this
^
SyntaxError: EOL while scanning string literal
不过,能用 setattr 设置属性,自然就可以用 getattr 取出
使用计数器对象进行计数¶
这是 collections 库中的一个 dict 子类,专门用于解决计数问题, 子类还包括 most_common 等方法
from collections import Counter
c = Counter('hello world')
>>> c
Counter({'l': 3, 'o': 2, ' ': 1, 'e': 1, 'd': 1, 'h': 1, 'r': 1, 'w': 1})
>>> c.most_common(2)
[('l', 3), ('o', 2)]
collections 库中的其他方法,稍后进行总结 collections 总结
漂亮的打印 JSON¶
使用 indent 关键字参数即可偏亮的打印 JSON
>>> import json
>>> print(json.dumps(data)) # No indention
{"status": "OK", "count": 2, "results": [{"age": 27, "name": "Oz", "lactose_intolerant": true}, {"age": 29, "name": "Joe", "lactose_intolerant": false}]}
>>> print(json.dumps(data, indent=2)) # With indention
{
"status": "OK",
"count": 2,
"results": [
{
"age": 27,
"name": "Oz",
"lactose_intolerant": true
},
{
"age": 29,
"name": "Joe",
"lactose_intolerant": false
}
]
}
无限循环的结束¶
# 不推荐
file = open("some_filename", "r")
while 1: # infinite loop
line = file.readline()
if not line: # 'readline()' returns None at end of file.
break
# Process the line.
file = open("some_filename", "r")
# 推荐
for line in file:
# Process the line.
另外,open 函数的功能也可由 file 替代
here starts my collection¶
或的另一种写法¶
# way 1
if i==a or i==b:
pass
# way 2
if i in (a, b):
pass