吐槽 Python 的 *args, **kwargs

4 天前
 justdoit123
接手一个数据拷贝的任务,在老代码里看到大量 def xxx_fn(*args, **kwargs) 真的血压升高。

这两兄弟里面“什么都有,又什么都没有“,反正全靠猜。

没有注释,就算有注释,随时时间迁移也未必准确。

从最外层到最内层,每一层都有可能往 kwargs 里塞参数或者 pop 参数。

这样的代码心智负担大,理解起来效率低。

这种写法一点也不酷,真的要慎重是用。另外要吐槽,python 社区还有大量这种库(包括官方自带的库),不过幸好质量好一点库都有参数注释,而且(应该是)有持续维护。


我也在思考,为什么各类语言要有那么多酷炫无比的特性?我认为,这些特性大部分是为基础库服务的。上层逻辑代码乱用这种特性,只会给自己找麻烦。


一下省略 “*args, **kwargs“ 个字
3160 次点击
所在节点    Python
48 条回复
miaotaizi
4 天前
"屎中一坨", 别说什么 “人生苦短”, 不接受反驳
NoOneNoBody
4 天前
params = ((1,2,3), (4,5,6,7), ...)
result = 0
for i,fun in enumerate((fun1, fun2, fun3, ...)): result=fun(result, *params[i])
print(result)

有些时候,上述 1,2,3 或 4,5,6,7 这些参数就是从上游得到的结果,只需按需顺列好传到下游计算,不需要理会其具体意义,这时候,args 就很有用了
例如上述代码写成闭包,只需传 params 和 result 初始值,就能完成一长串的计算,不需要记太多参数意义,可能更重要的点是 fun1/fun2/fun3...的顺序

数据预处理、标准化经常就是这样枯燥的,步骤和参数固定,机械化按顺序执行就是了
爬虫也是,无非就是 bs4+selector ,re+pattern ,lxml+xpath ,函数形式基本固定,变化只是 selector/pattern/xpath 这些,bs4/re/lxml 谁先谁后可能更重要

其实还有其他用法,如参数“补齐”
有十个参数,参数名都是固定的,有若干个 fun 都用这些同名参数,fun1 只用到 3 个,fun2 只用到 7 个……,可以全部十个都用 kwargs 传进去,传多了也不会错,不用逐个 fun 检查并选择哪些参数。例如处理图片,很多函数都是用相同的参数名,其意义也固定的,什么宽高、通道数……如果已知足够多参数,一起用 kwargs 传过去也不会错的,除非这个用 w/h 表示宽高,那个用 width/height 表示宽高,这就麻烦了
miaotaizi
4 天前
@NoOneNoBody 为什么不把你的 10 个参数 做成一个对象?
winterbells
4 天前
更难受的是查找调用,结果弹出几十个无关路径,仅仅因为名字一样==
NoOneNoBody
4 天前
@miaotaizi #23
也可以啊,dataclass 就是这个用途吧,只是我没参透

def fun1(width, height): ...
def fun2(a, width,height): ...

params = {'width': 1920, 'height':1080}

fun1(**params)
a = 123
fun2(a, **params)
GeekGao
4 天前
语法糖能取代 BOB 大爷的设计模式吗 LMAO
至今为止尚未有语言可以做到吧。所以也别吐槽灵活性设计了。
justdoit123
4 天前
没有攻击语言的意思。 估计这也是工程演进的产物。

也不是只是单纯的吐槽。 真的建议不要乱用语言特性。
liprais
4 天前
你都用 python 了还纠结这些
genesislive
4 天前
matplotlib 里面应该有不少
mywaiting
4 天前
别人写的 *args **kwargs 什么垃圾,类型标识都没有,简直屎山! python 垃圾语言!
自己一把梭 *args **kwargs 内部各种对 kwargs 一会 pop 一会 setdefault 真香!干净简洁优雅! python 牛逼!
adoal
4 天前
用来做透传很方便
Vonrix
4 天前
每次用完就忘
ddkk1112
4 天前
许多第三方包特别喜欢用这两玩意
调用还得看一大堆文档,操
ytmsdy
4 天前
@Jinnrry 哈哈哈哈,确实,Python 里面的花式语法确实是最多的!就算 Python 的老司机,看到有些花式语法也要愣一下。
CodeCodeStudy
4 天前
@Jinnrry #13 golang 没有 any ,那是 typescript ,golang 的是 interface{}
InkStone
4 天前
也没啥好吐槽的,所有现存的静态类型语言都有相同的机制,更不要说动态类型的了。

C 里有 void*满天飞的代码,Java 也有很多人喜欢传 Map ,Golang interface{} 一把梭,Typescript 可以用 any 退化成多写几个字母的 javascript……
qq135449773
4 天前
这东西只能说仁者见仁智者见智了,IDE 静态分析足够强的话感觉问题还不算大
qW7bo2FbzbC0
4 天前
@CodeCodeStudy 新版本里面针对泛型类型指定,的确是 any 更符合语义,interface{}是 1.8 之前的用法了
lolizeppelin
4 天前
不能喷公司垃圾代码 转头喷 python 提供的功能 2333
lolizeppelin
4 天前
@ipwx
兄弟你论坛强度有点高啊..........感觉哪都能看到你 2333333333
真羡慕你啊...有那么多时间刷论坛 2333

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1078986

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX