移除控制标记(直接return 或 break)html
函数不该有反作用,单一职责原则,一个函数不该作两件事,函数粒度尽可能小python
合并重复的代码片断(if 和 else都有的代码,放到外面去)git
def get_width_height(): .... return width, height def get_area(width, height): return width, height # to class Rectangle(object): def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height def get_shape(): .... return Rectangle(height, width)
去除类 (类作的事很少,再也不独立存在)github
装饰器express
参考:http://www.wklken.me/posts/2017/06/17/refactoring-07.html#yuan-zejson
序号 | 快捷键 | 功能 |
---|---|---|
1 | F5 | 复制文件 |
2 | F6 | 移动文件 |
3 | SHIFT F6 | 重命名 |
4 | ALT delete | 安全删除 |
5 | CTRL F6 | 改变函数形参 |
6 | CTRL ALT M | 将代码提取为函数 |
7 | CTRL ALT V | 将代码提取为变量 |
8 | CTRL ALT C | 将代码提取为常数 |
9 | CTRL ALT F | 将代码提取为字段 |
10 | CTRL ALT P | 将代码提取为参数 |
每当你在代码库中看到如下的模式能够参照如下的建议进行重构,让代码变得更加的pythonic,可读性更好,更容易维护。
参考:Python重构代码的一些模式 http://mpwang.github.io/2017/08/26/python-refactor-patterns/安全
须要使用列表的下标时,不要使用C风格的下标遍历app
lst = ['a', 'b', 'c'] # DON'T i = 0 for i in lst: print i, '-->', lst[i] i += 1 # OR for i in range(len(lst)): print(i, '-->', lst[i]) # DO for idx, item in enumerate(lst): print(idx, '-->', item)
同时遍历两个列表时,不要使用C风格的下标遍历ide
lst1 = ['a', 'b', 'c'] lst2 = [1, 2, 3] # DON'T for i in range(len(lst1)): print(lst1[i]) print(lst2[i]) # DO for lst1_item, lst2_item in zip(lst1, lst2): print(lst1_item) print(lst2_item) # BETTER # 不须要在内存中生成包含lst, lst2的第三个列表 from itertools import izip for lst1_item, lst2_item in izip(lst1, lst2): print(lst1_item) print(lst2_item)
x, y = y, x foo, bar, _ = words # 使用 _ 若是你不须要这个值
处理字典中key不存在时的默认值函数
# group words by frequency words = [(1, 'apple'), (2, 'banana'), (1, 'cat')] frequency = {} # DON'T for freq, word in words: if freq not in frequency: frequency[freq] = [] frequency[freq].append(word) # DO for freq, word in words: frequency.setdefault(freq, []).append(word) # BETTER from collections import defaultdict frequency = defaultdict(list) for freq, word in words: frequency[freq].append(word) # 在工做中要常常处理字典为空或键值不存在的情形,用get和setdefault代替dict_name['key']
setdefault vs get
setdefault()的使用,相似get方法,若是字典中包含有给定键,则返回该键对应的值,不然返回为该键设置的值
不一样点:1.setdefault会把不存在的item保存到原来的dict,2.setdefault比get快10percent
person_dict = {} person_dict['liqi'] = 'LiQi' person_dict.setdefault('liqi', 'Liqi') # 'LiQi' person_dict.setdefault('Kim', 'kim') # 'kim' person_dict person_dict.get('Dim', 'D') # 'D' person_dict # {'liqi': 'LiQi', 'Kim': 'kim'}
遍历字典
words = {'apple': 1, 'banana': 2, 'cat': 3} # OK for word in words: print word, '-->', words[word] # 须要计算word的hash值 # GOOD for word, freq in words.items(): print word, '-->', freq # BETTER # 不须要在内存中生存包含words全部元素的中间结果 for word, freq in words.iteritems(): print word, '-->', freq
break and nobreak
# DO for word in words: if condition(word): # 处理存在符合condition的元素的状况 print 'Found' break else: # 处理没有符合condition元素的状况 print 'Not found'
分开异常处理与正常状况
# GOOD try: result = json.loads(get_external_json()) do_something_with(result) except Exception as e: handle_error(e) # BETTER try: # 异常可能抛出点 result = json.loads(get_external_json()) except Exception as e: # 异常处理 handle_error(e) else: # 正常状况 do_something_with(result)
https://medium.com/the-andela-way/idiomatic-python-coding-the-smart-way-cc560fa5f1d6
# bad if x <= y and y <= z: # do something # good if x <= y <= z: # do something
For example an empty list/sequences [], empty dictionaries {} None, False, Zero for numeric types, are considered “falsy”. On the other hand, almost everything else is considered “truthy”.
# bad x = True y = 0 if x == True: # do something elif x == False: # do something else if y == 0: # do something ls = [2, 5] if len(ls) > 0: # do something # good (x, y) = (True, 0) # x is truthy if x: # do something else: # do something else # y is falsy if not y: # do something ls = [2, 5] if ls: # do something
# bad a = True value = 0 if a: value = 1 print(value) # good a = True value = 1 if a else 0 print(value)
# bad city = 'Nairobi' found = False if city == 'Nairobi' or city == 'Kampala' or city == 'Lagos': found = True # good city = 'Nairobi' found = city in {'Nairobi', 'Kampala', 'Lagos'}
# bad def check_equal(x, y): result = False if x == Y: result = True return result # good def check_equal(x, y): return x == y
# good x = y = z = 'foo'
def user_info(user): return 'Name: {user.name} Age: {user.age}'.format(user=user)
ls = [element for element in range(10) if not(element % 2)] emails = {user.name: user.email for user in users if user.email}
ls1 = [1, 2, 3, 4, 5] ls2 = [4, 5, 6, 7, 8] elements_in_both = list( set(ls1) & set(ls2) ) print(elements_in_both)
# bad if user: print('------------------------------') print(user) print('------------------------------') # good if user: print('{0}\n{1}\n{0}'.format('-'*30, user))