
code review 代码,功能是“读取 CSV 文件,过滤掉空行,转成字典列表”。
写了 87 行。
我盯着屏幕看了三秒,敲了一行看实现的功能一样:
data = [dict(r) forrincsv.DictReader(open("data.csv")) ifany(r.values())]今天把这种“能用一行解决,却写了一百行”的场景全部整理出来。每一条都是我真实踩过的,或者 review 时亲眼见过的。
新手写法(12行):
defread_file(path):
result = ""
withopen(path, 'r', encoding='utf-8') asf:
lines = f.readlines()
forlineinlines:
result += line
returnresult一行搞定:
content = open("file.txt", encoding="utf-8").read()with 语句虽然更规范(能自动关文件),但如果你只是临时读个文件脚本,一行足以。
新手写法(9行):
defdedupe(items):
seen = set()
result = []
foriteminitems:
ifitemnotinseen:
seen.add(item)
result.append(item)
returnresult一行搞定:
result = list(dict.fromkeys(items))dict.fromkeys() 按插入顺序保留 key,Python 3.7+ 字典是有序的,去重同时保序一步到位。
新手写法(8行):
defflatten(nested):
result = []
forsublistinnested:
foriteminsublist:
result.append(item)
returnresult一行搞定:
flat = [itemforsublistinnestedforiteminsublist]嵌套列表推导,读两遍就习惯了。如果是多层嵌套(三维以上)用 itertools.chain:
importitertools
flat = list(itertools.chain.from_iterable(nested))新手写法(3行):
temp = a
a = b
b = temp一行搞定:
a, b = b, a这是 Python 最基本的语法糖,但真有不少人不知道。我在面试里问过,有人当场愣住。
新手写法(7行):
defreverse_string(s):
result = ""
foriinrange(len(s)-1, -1, -1):
result += s[i]
returnresult一行搞定:
reversed_s = s[::-1]切片 [::-1] 是 Python 里最优雅的反转操作。列表也一样:lst[::-1]。
新手写法(14行):
defmost_common(items):
counts = {}
foriteminitems:
counts[item] = counts.get(item, 0) +1
max_count = 0
result = None
foritem, countincounts.items():
ifcount>max_count:
max_count = count
result = item
returnresult一行搞定:
fromcollectionsimportCounter
result = Counter(items).most_common(1)[0][0]Counter 是标准库里最被低估的工具之一。统计词频、投票结果、日志分析,全能用上。
新手写法(6行):
defmerge_dicts(d1, d2):
result = {}
fork, vind1.items():
result[k] = v
fork, vind2.items():
result[k] = v
returnresult一行搞定(Python 3.9+):
merged = d1|d2更早版本用 merged = {**d1, **d2},同样一行。
新手写法(4行):
if"name"inuser:
name = user["name"]
else:
name = "匿名"一行搞定:
name = user.get("name", "匿名")get() 第二个参数是默认值,不存在时不会抛 KeyError。
新手写法(8行):
defall_positive(nums):
forninnums:
ifn<= 0:
returnFalse
returnTrue一行搞定:
all_positive = all(n>0forninnums)
any_positive = any(n>0forninnums)all() 和 any() 配合生成器表达式,干净得不行。
新手写法(4行):
i = 0
foriteminitems:
print(i, item)
i += 1一行搞定:
fori, iteminenumerate(items):
print(i, item)enumerate() 还能指定起始索引:enumerate(items, start=1) 让序号从 1 开始。
新手写法(9行):
defchunk(lst, size):
result = []
foriinrange(0, len(lst), size):
result.append(lst[i:i+size])
returnresult一行搞定(Python 3.12+):
fromitertoolsimportbatched
chunks = list(batched(lst, 3))3.12 以下版本,用列表推导:
chunks = [lst[i:i+3] foriinrange(0, len(lst), 3)]新手写法(12行):
defflatten_and_dedupe(nested):
result = []
seen = set()
forsublistinnested:
foriteminsublist:
ifitemnotinseen:
seen.add(item)
result.append(item)
returnresult一行搞定:
importitertools
result = list(dict.fromkeys(itertools.chain.from_iterable(nested)))链式调用,从左到右读一遍就懂。
新手写法(7行):
deffactorial(n):
result = 1
foriinrange(1, n+1):
result *= i
returnresult一行搞定:
importmath
result = math.factorial(n)别自己写阶乘,标准库有,而且是 C 实现的,快得多。
新手写法(7行):
defis_palindrome(s):
foriinrange(len(s)//2):
ifs[i] != s[len(s)-1-i]:
returnFalse
returnTrue一行搞定:
is_palindrome = s == s[::-1]切片反转比对,回文判断的终极答案。
新手写法(20行+):
defcount_words(path):
result = {}
withopen(path) asf:
forlineinf:
words = line.split()
forwordinwords:
word = word.lower().strip(".,!?")
result[word] = result.get(word, 0) +1
returnresult核心逻辑一行搞定:
fromcollectionsimportCounter
importre
counts = Counter(re.findall(r"\w+", open("file.txt").read().lower()))写 Python 这几年,我对“一行代码”这件事的看示变了好几次。
刚学的时候觉得写一行很酷,刻意把各种逻辑挤到一起,结果同事看我的代码像看天书。后来走另一个极端,什么都拆开写,明明一行能搞定的事硬写十行,美其名曰“可读性”。
现在觉得,标准库提供的方法,能用就用。上面 15 个例子里 10 个用的是标准库,多看 itertools、collections、functools 的文档,能省大量时间。
但别为了短而短。有人喜欢把十行逻辑硬挤成一行,那不叫优雅,叫难维护。我见过最长的一行有 247 个字符,改 bug 的时候骂了一整天。
“无他,惟手熟尔”!有需要的用起来!
本文分享自 Nicholas与Pypi 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!