文章目錄
更簡潔的推導式
if else
# Q: 從服務器返回的響應可能是文本, 也可能是 null, 請判斷當爲 null 時, 轉換爲 ''
# == Good ==
if response is None:
data = ''
else:
data = response
# == Better ==
data = '' if response is None else response
# == Best ==
data = response or ''
list comprehension vs filter
# Q: 已知一個數字組成的列表, 獲取裏面大於 0 的數字
alist = [1, 0, -1, 2]
# == Good ==
positive_num = (x for x in alist if x > 0)
# == Better ==
positive_num = filter(lambda x: x > 0, alist)
海象運算符 (Python 3.8)
# Q: 書架上有 a 本書, 用戶借了 b 本, 請分別打印 a, b 和 b / a 的百分比值
# == Bad ==
print('書架上有 {} 本書, 用戶借閱 {} 本, 佔比 {}%'.format(
len(total_books),
len(rent_books),
round(len(rent_books) / len(total_books) * 100, 2)
))
# == Good ==
a = len(total_books)
b = len(rent_books)
print('書架上有 {} 本書, 用戶借閱 {} 本, 佔比 {}%'.format(
a, b, round(b / a * 100, 2)
))
# == Better ==
print('書架上有 {} 本書, 用戶借閱 {} 本, 佔比 {}%'.format(
a := len(total_books),
b := len(rent_books),
round(b / a * 100, 2)
))
reduce 遞歸替換
# Q: 請將 text 中的 A 替換爲 Apple, B 替換爲 Banana, 得到一個新文本
text = 'A;B'
translator = {'A': 'Apple', 'B': 'Banana'}
# == Good ==
new_text = text
for k, v in translator.items():
new_text = new_text.replace(k, v)
# == Tricky ==
from functools import reduce
new_text = reduce(lambda x, args: x.replace(*args), translator.items(), text)
列表展平
pass
字典合併
a = {'A': 'Apple', 'B': 'Banana'}
b = {'A': 'Almond', 'C': 'Cherry'}
merged = {**a, **b}
# -> {'A': 'Almond', 'B': 'Banana', 'C': 'Cherry'}
更合理的做法
類變量
# == Bad ==
class AAA:
# 會產生單例對象 (如果這不是你想要的話)
keywords = ['first', 'second', 'third']
def __init__(keywords=None):
if keywords:
self.keywords.extend(keywords)
# == Good ==
class BBB:
def __init__(keywords=None):
self.keywords = ['first', 'second', 'third']
if keywords:
self.keywords.extend(keywords)
# == Better ==
class CCC:
keywords: list # 這樣做有利於子類繼承時, 更安全地覆寫
def __init__(keywords=None):
self.keywords = ['first', 'second', 'third']
if keywords:
self.keywords.extend(keywords)
變量命名習慣 (僅供參考!)
對稱好於不對稱
注: 僅建議在局部範圍嘗試.
# == Good ==
benchmark = Benchmark()
select = Select()
provide = Provide()
# == Obsessive ==
bcmk = Benchmark()
slct = Select()
prvd = Provide()
# ------------------------------------------------
# == Good ==
class Foo:
def fast_calc():
pass
def std_calc(): # std: standard
pass
# == Obsessive 1 ==
class Foo:
def fst_calc(): # fst: fast
pass
def std_calc(): # std: standard
pass
# == Obsessive 2 ==
class Foo:
def fast_calc():
pass
def stnd_calc(): # stnd: standard
pass
語義明確好於語義簡潔
# == Bad ==
er = ExcelReader()
ew = ExcelWriter()
fr = FileReader()
fw = FileWriter()
# == Good ==
reader1 = ExcelReader()
writer1 = ExcelWriter()
reader2 = FileReader()
writer2 = FileWriter()
# == Better ==
exl_reader = ExcelReader()
exl_writer = ExcelWriter()
file_reader = FileReader()
file_writer = FileWriter()
格式一致好於格式不一致
class MyFinder:
def find_one(self, x):
pass
def find_last(self, x):
pass
# == Not Good ==
def findall(self, x):
pass
# == Good ==
def find_all(self, x):
pass
使用 i-, o- 前綴表示 “輸入”, “輸出”
# (建議在局部變量使用)
for ifile, ofile in file_io.items():
ilist = get_list_from_file(ifile)
olist = handle_list(ilist)
write_result(olist, ofile)
目錄路徑末尾不加斜槓
idir = '../data'
odir = '../output'
for name in name_list:
ifile = f'{idir}/{name}.html'
ofile = f'{odir}/{name}.json'
...
爲什麼?
顯式的斜槓更易於閱讀. 這點類似於百分號, 查看下面的例子:
# == Bad ==
def calc_percent_1(m, n):
return str(round(m / n * 100, 2)) + '%'
# == Good ==
def calc_percent_2(m, n):
return round(m / n * 100, 2)
print('當前的工作進度是 {}'.format(calc_percent_1(1, 3)))
print('當前的工作進度是 {}%'.format(calc_percent_2(1, 3)))
前者在易讀性上更差一些. 特別是當計算百分比的函數和 print 在不同的 py 文件時, 前者更容易讓人忽略掉它是百分數的事實. (而且 calc_percent_1
在函數 “單一職能” 的表達上也不如 calc_percent_2
)
路徑的斜槓的使用原則和這個百分號示例有着相同之處. 這是爲什麼不推薦在目錄路徑末尾加斜槓的原因.
代碼風格 (非 PEP8 範疇, 僅供交流)
減少嵌套, 儘快返回
注: 僅在單個函數內涉及的條件判斷過多時使用.
== Bad ==
pass
== Good ==
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fHH12uX4-1579151769273)(…/附件/圖片/2019/20200116113121.png)]
項目目錄結構 (僅供參考!)
# 適合個人目錄
# 豎線 (|) 表示別名
myproj
bin: 字節碼文件, 可執行文件 (可選)
conf | config | settings: 配置文件 (可選, 可整合到 data)
config.json: 總配置文件
data | model: 數據, 模型
cache: 緩存 (可選, 可調整爲一級目錄)
docs: 文檔或資料文件
sample | demo | examples: 樣本 (可選, 可調整爲一級目錄)
dustbin: 臨時的回收站 (可選)
lib: 第三方庫 (可選)
log: 日誌文件 (可選, 可調整爲二級目錄)
src | myproj | code | core: 源碼目錄
utils | tools: 工具類腳本 (可選, 可調整爲一級目錄)
sidework: 非主線腳本 (可選)
main.py | app.py | launch.py | launcher.py | run.py: 啓動文件, 主入口
output | report
res | resource | source: 資源文件 (可選, 可整合到 data)
temp (可選)
in.txt
out.txt
tmp.py
tests | testflight (可選)
venv | env: 環境和依賴 (可選)
CHANGELOG.txt | CHANGELOG: 更新日誌 (可整合到 docs)
README.md | README: 自述文檔 (可整合到 docs)
示例 (截圖如下):
下載項目目錄模板: https://www.lanzous.com/i7dgf3e
參考
- Python代碼怎麼寫,聽聽頂尖Python大神 kennethreitz 的建議 - 雲+社區 - 騰訊雲 https://cloud.tencent.com/developer/news/332901
- chiphuyen/python-is-cool https://github.com/chiphuyen/python-is-cool
- Python 有哪些讓你相見恨晚的技巧? - 量子位的回答 - 知乎 https://www.zhihu.com/question/48755767/answer/873187244
- 改善 Python 程序的 91 個建議 https://mp.weixin.qq.com/s?__biz=MjM5NzEyMzg4MA==&mid=2649413298&idx=2&sn=88080e190f8ace42c8d5b0a1a9323426&chksm=bec0b4f589b73de379a081e77da32db66a1fa8db4e94236af203a1a995bd6b8a4fbc7c9b9a3c
- 如何合理的規劃一個 python 的項目目錄? - V2EX - https://www.v2ex.com/t/229241
- What is the best project structure for a Python application? - Stack Overflow https://stackoverflow.com/questions/193161/what-is-the-best-project-structure-for-a-python-application
- python基礎6–目錄結構 - Bigberg - 博客園 https://www.cnblogs.com/bigberg/p/6423164.html