吐槽 Python 的 *args, **kwargs

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

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

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

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

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

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


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


一下省略 “*args, **kwargs“ 个字
4151 次点击
所在节点   Python  Python
49 条回复
miaotaizi
miaotaizi
133 天前
"屎中一坨", 别说什么 “人生苦短”, 不接受反驳
NoOneNoBody
NoOneNoBody
133 天前
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
miaotaizi
133 天前
@NoOneNoBody 为什么不把你的 10 个参数 做成一个对象?
winterbells
winterbells
133 天前
更难受的是查找调用,结果弹出几十个无关路径,仅仅因为名字一样==
NoOneNoBody
NoOneNoBody
133 天前
@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
GeekGao
133 天前
语法糖能取代 BOB 大爷的设计模式吗 LMAO
至今为止尚未有语言可以做到吧。所以也别吐槽灵活性设计了。
justdoit123
justdoit123
133 天前
没有攻击语言的意思。 估计这也是工程演进的产物。

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

C 里有 void*满天飞的代码,Java 也有很多人喜欢传 Map ,Golang interface{} 一把梭,Typescript 可以用 any 退化成多写几个字母的 javascript……
qq135449773
133 天前
这东西只能说仁者见仁智者见智了,IDE 静态分析足够强的话感觉问题还不算大
qW7bo2FbzbC0
133 天前
@CodeCodeStudy 新版本里面针对泛型类型指定,的确是 any 更符合语义,interface{}是 1.8 之前的用法了
lolizeppelin
133 天前
不能喷公司垃圾代码 转头喷 python 提供的功能 2333
lolizeppelin
133 天前
@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