移除控制標記(直接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))