python代码整洁之道

1、真值判断

检查某个对象是否为真值时,还显示的与 True 和 False 做比较,这就显得多此一举

  • unpythonic
if attr == True:
    do_something()

if len(values) != 0: # 判断列表是否为空
    do_something()
  • pythonic
if attr:
    do_something()

if values:
    do_something()

真假值对照表:

类型 False True
布尔 False(与0等价) True(与1等价)
数值 0, 0.0 非零的数值
字符串 '', ""(空字符串) 非空字符串
容器 [], (), {}, set() 至少有一个元素的容器对象
None None 非None对象

2、预设字典默认值

通过 key 分组的时候,不得不每次检查 key 是否已经存在于字典中。

  • unpythonic
data = [('foo', 10), ('bar', 20), ('foo', 39), ('bar', 49)]
groups = {}
for (key, value) in data:
    if key in groups:
        groups[key].append(value)
    else:
        groups[key] = [value]
  • pythonic
# 第一种方式
groups = {}
for (key, value) in data:
    groups.setdefault(key, []).append(value) 

# 第二种方式
from collections import defaultdict
groups = defaultdict(list)
for (key, value) in data:
    groups[key].append(value)

结果:

{'foo': [10, 39], 'bar': [20, 49]}

setdefault:

Python 字典 setdefault() 方法和 get()方法 类似, 如果键不存在于字典中,将会添加键并将值设为默认值。

defaultdict:

defaultdict是Python内建dict类的一个子类,第一个参数为default_factory属性提供初始值,默认为None。它覆盖一个方法并添加一个可写实例变量。它的其他功能与dict相同,但会为一个不存在的键提供默认值,从而避免KeyError异常。

# 统计某个单词出现的次数, 并选出排名前三的单词

from collections import defaultdict

words = ('python', 'python', 'hello', 'world', 'world', 'world', 'man')
counts = defaultdict(lambda: 0)
for word in words:
    counts[word] += 1

sorted_words = sorted(counts.items(), key=lambda x: x[1], reverse=True)

print(sorted_words[:3])

3、列表推导式(生成式)

构建列表对象一般使用下面这种方式,可读性非常差

  • unpythonic
test_list = []
for i in range(10):
    test_list.append(i*2)
  • pythonic
test_list = [i*2 for i in range(10)]

比如:找出员工工资低于当地最低工资标准(<$9)的公司名称

  • unpythonic
companies = {
    'CoolCompany': {'Alice': 33, 'Bob': 28, 'Frank': 29},
    'CheapCompany': {'Ann': 4, 'Lee': 9, 'Chrisi': 7},
    'SosoCompany': {'Esther': 38, 'Cole': 8, 'Paris': 18}
}

illege_companies1 = []
for company in companies:
    for salary in companies[company].values():
        if salary < 9:
            illege_companies1.append(company)
            
print(set(illege_companies1))
  • pythonic
companies = {
    'CoolCompany': {'Alice': 33, 'Bob': 28, 'Frank': 29},
    'CheapCompany': {'Ann': 4, 'Lee': 9, 'Chrisi': 7},
    'SosoCompany': {'Esther': 38, 'Cole': 8, 'Paris': 18}
}

illege_companies2 = [company for company in companies if any(salary < 9 for salary in companies[company].values())]

print(illege_companies2)

# python的any()函数。它接受一个可迭代对象,比如列表,如果这个可迭代对象中至少有一个的真值判断为True,它就会返回True。例如,表达式any([True,False,False,False])的结果为True,而any([2<1,3+2>5+5,3-2<0,0])的结果为False。

比如:把字段名称添加到员工数据里,由此创建出一个由字典构成的列表,每个字典中将字段名分配给对应的值

column_names = ['name', 'salary', 'job']
db_rows = [('Alice', 180000, 'data scientist'), ('Bob', 99000, 'mid-level manager'), ('Frank', 87000, 'CEO')]

employee_info = [dict(zip(column_names, db)) for db in db_rows]

# zip压缩后是元组,为不能hash的数据类型,也就是不可变的类型,所以不能用字典解析式,因为其不可hash
print(employee_info)

4、切片赋值

  • pythonic
visitors = ['Firefox', 'corrupted', 'Chrome', 'corrupted',
            'Safari', 'corrupted', 'Safari', 'corrupted',
            'Chrome', 'corrupted', 'Firefox', 'corrupted']

# 想要得到的结果是这样,也就是偶数位的都是需要被替换的前一位的值

new_visitors = ['Firefox', 'Firefox', 'Chrome', 'Chrome',
                'Safari', 'Safari', 'Safari', 'Safari',
                'Chrome', 'Chrome', 'Firefox', 'Firefox']

visitors[1::2] = visitors[::2]

print(visitors)

5、匿名函数

匿名函数 lambda 和常规函数一样,返回的都是一个函数对象。

匿名函数最难理解的地方就是要传入的参数是一个可迭代的对象,lambda 内部会调用可迭代对象的 next 方法取值当作参数传入 lambda 函数冒号前面的值,然后把表达式计算的结果进行返回。

  • unpythonic
# 计算平方

def square(x):    
    return x**2

squared = map(square, [1, 2, 3, 4, 5])

# 常规函数 def 必须通过其函数名被调用,因此必须首先被定义,另外,注意map调用的是函数名称
  • pythonic
squared = map(lambda x: x**2, [1, 2, 3, 4, 5])
  • unpythonic
# 过滤操作

a = [3, 4, 5]
b = []
for i in a:
    if i > 4:
        b.append(i)
  • pythonic
b = filter(lambda x: x > 4, a)

#filter函数,它和 map 函数类似,function 同样表示一个函数对象。filter() 函数表示对 iterable 中的每个元素,都使用 function 判断,并返回 True 或者 False,最后将返回 True 的元素组成一个新的可遍历的集合。
# 累积操作
from functools import reduce

l = [1, 2, 3, 4, 5]

product = reduce(lambda x, y: x * y, l) # 1*2*3*4*5 = 120

# educe(function, iterable) 函数,它通常用来对一个集合做一些累积操作。function 同样是一个函数对象,规定它有两个参数,表示对 iterable 中的每个元素以及上一次调用后的结果,运用 function 进行计算,所以最后返回的是一个单独的数值。

6、访问字典元素

  • unpythonic
#如果字段中存在某键时,打印其值,否则给其赋上默认值

d = {'hello': 'world'}
if d.has_key('hello'):
    print d['hello']    # prints 'world'
else:
    print 'default_value'
  • pythonic
d = {'hello': 'world'}

print d.get('hello', 'default_value') 
# prints 'world'
print d.get('thingy', 'default_value') 
# 不存在‘thingy’键,于是赋值为'default_value'

# Or:
if 'hello' in d:
    print d['hello']

参考

1、https://foofish.net/idiomatic_part2.html

2、https://www.cnblogs.com/wongbingming/p/13781104.html

posted @ 2022-04-12 17:30  xyztank  阅读(185)  评论(0编辑  收藏  举报