关于Pythonic定义,参考文章:What does pythonic mean?
以下通过对比Bad way和Elegant way介绍一些常见的Pythonic写法。
使用字典默认值
需求:在取dict的值的时候,假设某个key不存在,希望赋予其一个默认的值。
比较糟糕的方式:使用if去判断key是否存在,不存在则给其赋予默认值。如下:
person = {
"name": "xiaohong",
"age": 12,
}
name = person['name'] if person.get('name') else "nobody"
优雅的写法:
name = person.get("name", "nobody")
dict类型的get方法是可以设置缺省值的。
使用enumerate关键字
需求:对列表进行迭代的时候,需要同时访问偏移量。
比较糟糕的方式:定义一个起始索引值,每迭代一次索引值计数一次。如下:
names = ["Zhang san", "Li si", "Wang wu"]
index = 0
for name in names:
print("The {0} is in position: {1}".format(name, index))
index += 1
或者
names = ["Zhang san", "Li si", "Wang wu"]
for position in range(0, len(names)):
print("The {0} is in position: {1}".format(names[position], position))
优雅的写法:
names = ["Zhang san", "Li si", "Wang wu"]
for position, name in enumerate(names):
print("The {0} is in position: {1}".format(name, position))
用enumerate关键字进行迭代的过程中可同时返回索引以及值。
for else的巧用
需求:在一个列表中查找某个元素,如果,找到这个元素,立刻结束查找;如果未查找到则打印未找到。
比较糟糕的方式:定义一个变量用来标示是否找到。如下:
names = ["Zhang san", "Li si", "Wang wu"]
for name in names:
if name == 'Gou er dan':
found = True
break
if found is False:
print("未找到")
优雅的写法:
names = ["Zhang san", "Li si", "Wang wu"]
found = False
for name in names:
if name == 'Gou er dan':
found = True
break
else:
print("未找到")
for else语句,如果for循环执行完毕,则会执行else语句块,否则,不执行else语句块。
with关键字的使用
需求:读写文件或者使用进程锁。
比较糟糕的方式,手动管理文件的关闭或者打开。如:
f = open("test.txt", "r")
try:
text = f.read()
print(text)
finally:
f.close()
或者
import threading
lock = threading.Lock()
lock.acquire()
try:
print("Balabala")
finally:
lock.release()
优雅的写法:
with open("test.txt", "r") as f:
print(f.read())
和
import threading
lock = threading.Lock()
with lock:
print("balabala")
使用with避免自己手动释放资源。
同时遍历二个列表
需求:同时遍历二个列表。
比较糟糕的方式,定义下标去索引,如:
numbers = [1, 2, 3, 4]
english = ['one', 'two', 'three']
n = min(len(numbers), len(english))
for i in range(n):
print("{0} is {1}".format(numbers[i], english[i]))
优雅的写法:
numbers = [1, 2, 3, 4]
english = ['one', 'two', 'three']
for number, name in zip(numbers, english):
print("{0} is {1}".format(number, name))
使用takewhile代替break
需求:在每次循环开始时,判断循环是否需要提前结束。
不地道的写法:使用break。如:
for user in users:
if not is_qualified(user):
break
地道的写法:
from itertools import takewhile
for user in takewhile(is_qualified, users):
# ....
对于这类需要提前中断的循环,我们可以使用 takewhile() 函数来简化它。takewhile(predicate,iterable)会在迭代iterable的过程中不断使用当前对象作为参数调用predicate函数并测试返回结果,如果函数返回值为真,则生成当前对象,循环继续。否则立即中断当前循环。
使用defaultdict
需求:统计一组字符串出现的频率。
不优雅的写法:
names = ["Zhang san", "Li si", "Li si", "Wang wu", "Zhang san", "Wang wu"]
name_count = dict()
for name in names:
if not name_count.get(name):
name_count['name'] = 0
else:
name_count['name'] += 1
优雅的写法:
from collections import defaultdict
names = ["Zhang san", "Li si", "Li si", "Wang wu", "Zhang san", "Wang wu"]
name_count = defaultdict(int)
for name in names:
name_count[name] += 1
更加优雅的写法:
from collections import Counter
names = ["Zhang san", "Li si", "Li si", "Wang wu", "Zhang san", "Wang wu"]
print(Counter(names))
还有很多,下次接着写...
并且,继续更新中 ...