提问人:Dan Chrostowski 提问时间:12/22/2016 最后编辑:Dan Chrostowski 更新时间:12/23/2016 访问量:225
有没有更好的替代方法,可以将可变的可选参数保留为参数,而其值不会在 Python 的后续调用中保留?
Is there a better alternative to keeping a mutable optional argument as a parameter without its value persisting on subsequent calls in Python?
问:
不恰当地标记为重复问题。这与不知道如何通过引用传递变量无关。它询问是否有一种方法可以缓解将可变可选参数保留为参数的问题,而不会在后续调用时将其值保留在函数的上下文中。
因此,我今天刚刚遇到了这种情况,现在我熟悉了许多新的 Python 开发人员陷入的陷阱:可变默认参数。为简洁起见,以下是我所讨论的内容的一个示例:
def MyClass(object):
...
def my_func(self,my_str="default",my_dict={},**kwargs):
my_dict.update(kwargs)
self.my_dict = my_dict
----------------------------------------
<< a = MyClass()
<< a.my_func(foo='bar')
<< a.my_dict
>> {'foo':'bar'}
<< b = MyClass()
<< b.my_func(bar='baz')
<< b.my_dict
>> {'foo': 'bar', 'bar': 'baz'}
我知道这是故意的,并且理解一个好的解决方案是修改为此:my_func
def my_func(self,my_str="default",my_dict=None,**kwargs)
if my_dict is None: my_dict = {}
...
但是,我对此并不满意。它只是以错误的方式摩擦我。我不希望它默认为“无”。默认情况下,我想要一个空字典。于是我想到了这样做:
def my_func(self,my_str="default", my_dict={}, **kwargs)
my_dict.update(kwargs)
self.my_dict = my_dict
my_dict = {}
但这当然行不通,你会得到和以前一样的行为。但是为什么?持久性和可变性不是吗?还是只在 Python 方便的时候?除了简单地排除为可选参数之外,还有其他方法可以处理这个问题吗?my_dict
my_dict
我真的很挂断这个,因为我发现使用默认参数将类型传达给读者很有用,这提高了代码的可读性 IMO。这很好,因为读者不需要深入研究该函数来确定它应该是一个字典(inb4 建议“只使用评论”——理想主义,但对我的目的来说不是很现实)。my_dict
这个“功能”毫无意义,而且对我来说非常令人反感,以至于我实际上非常接近相信它真的是一个伪装的错误。没有人会使用它,这对我来说几乎是一个交易破坏者。
提前致谢。
答:
如果我理解正确的话,您认为通过赋值 ,您正在“重置”值,以便下次调用该函数时,它将再次为空。my_dict = {}
这不是默认参数的工作方式。相反,它的工作原理是这样的:
- 定义函数时,将创建一个“secret”对象,该对象包含参数的默认值。(您可以将此秘密对象视为普通函数,尽管如果您正在查看方法对象,则会有一些额外的复杂性。
func.__defaults__
- 每次调用该函数时,如果未传递给定参数的值,Python 会将该参数的值分配给以前存储的机密对象。
换句话说,Python 并没有真正存储跨调用的值。它存储一个默认值,并在每次调用时检索该值(除非您传递一个新值)。my_dict
当你这样做时,你只是给局部变量分配一个新值,这不会影响秘密对象。另一方面,当你做类似的事情时,你正在改变秘密对象。(如果你惊讶于赋值变量和调用方法有不同的效果,那么你应该在这里搜索很多关于赋值、变量绑定、可变对象与不可变对象等的 Python 问题。my_dict = {}
my_dict
my_dict.update()
update
评论
dictobj.clear()
my_dict.clear()
my_dict.clear()
my_func(my_dict=blah)
blah
blah
评论