美文网首页python自学Python
Pythonic(持续更新)

Pythonic(持续更新)

作者: HideOnStream | 来源:发表于2019-10-17 22:29 被阅读0次

关于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))

还有很多,下次接着写...
并且,继续更新中 ...

相关文章

网友评论

    本文标题:Pythonic(持续更新)

    本文链接:https://www.haomeiwen.com/subject/zrzvmctx.html