gpt4 book ai didi

python - **kwargs.pop(x) 与将 x 定义为函数参数

转载 作者:太空宇宙 更新时间:2023-11-04 01:52:29 38 4
gpt4 key购买 nike

假设您正在编写一个子类,它有一个构造函数,该构造函数将其未使用的 kwargs 传递给父构造函数,但是您的类有参数 x 它需要存储它不应该传递给 parent 。

我见过两种不同的方法:

def __init__(self, **kwargs):
self.x = kwargs.pop('x', 'default')
super().__init__(**kwargs)

def __init__(self, x='default', **kwargs):
self.x = x
super().__init__(**kwargs)

这两个构造函数之间是否存在任何功能差异?有什么理由要用一个而不是另一个吗?

我能看到的唯一区别是第二种形式,它在签名中定义了 x,允许用户更好地将其视为一个可能的参数,或将其作为自动完成提供的 IDE选项。或者在 Python 3.5+ 中,您可以向 x 添加类型注释。这会使第一种形式在客观上变得更糟吗?

最佳答案

正如 Giacomo Alzetta 在评论中提到的那样,第二个版本允许将 x 作为位置参数传递,而第一个版本只允许命名参数,IOW 与第二个形式你可以同时使用 Child(x=2) AND Child(2),而第一个仅支持 Child(x=2)

此外,当使用 inspection 检查方法的签名时,第二种形式会明确提及 x 参数的存在,而第一种形式不会。

最后,如果未传递 x,第二个版本将产生稍微更清晰的异常。

这就是功能差异。

Is there any reason to use one over the other?

嗯...作为一般规则,尽可能使用显式参数更清洁(最佳实践),即使只是为了可读性,而且根据经验,它通常确实使维护更容易。所以从这个角度来看,第二种形式可以看作比第一种形式“客观上更好”。

这就是说,当父方法有几十个主要是可选的和很少使用的参数时(django.forms.Form,我在看你)并且你还想保留位置参数顺序, 仅使用通用的 *args, **kwargs 签名并强制将附加参数作为 kwargs 传递可能很方便。假设你在文档字符串中清楚地记录了这一点,它仍然足够明确(就我而言,YMMV),并且还避免了很多困惑(你可以看看 django.forms.Form 有关我在这里的意思的具体示例)。

因此,与“最佳实践”和其他黄金法则一样,您必须根据手头的具体案例理解和权衡利弊。

PS:只是为了说清楚,django 的 Form 类签名非常合理,所以我不会在这里大声疾呼 - 这只是没有“漂亮”解决方案的情况之一问题,时期。

关于python - **kwargs.pop(x) 与将 x 定义为函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57707578/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com