修改** kwargs字典是否总是安全的? [英] Is it always safe to modify the `**kwargs` dictionary?
问题描述
使用Python函数语法def f(**kwargs)
,在该函数中创建了关键字参数字典kwargs
,并且字典是可变的,所以问题是,如果我修改kwargs
字典,是否有可能在我的功能范围之外有什么影响?
Using the Python function syntax def f(**kwargs)
, in the function a keyword argument dictionary kwargs
is created, and dictionaries are mutable, so the question is, if I modify the kwargs
dictionary, is it possible that I might have some effect outside the scope of my function?
从我对字典解压缩和关键字参数打包的工作原理的理解中,我看不出有任何理由相信它可能是不安全的,而且在我看来,在Python 3.6中没有这种危险:
From my understanding of how dictionary unpacking and keyword argument packing works, I don't see any reason to believe it might be unsafe, and it seems to me that there is no danger of this in Python 3.6:
def f(**kwargs):
kwargs['demo'] = 9
if __name__ == '__main__':
demo = 4
f(demo=demo)
print(demo) # 4
kwargs = {}
f(**kwargs)
print(kwargs) # {}
kwargs['demo'] = 4
f(**kwargs)
print(kwargs) # {'demo': 4}
但是,此实现特定于Python,还是它是Python规范的一部分?我是否会忽略任何情况或实现(除非对自己可变的参数进行修改,例如kwargs['somelist'].append(3)
)可能会出现这种情况?
However, is this implementation-specific, or is it part of the Python spec? Am I overlooking any situation or implementation where (barring modifications to arguments which are themselves mutable, like kwargs['somelist'].append(3)
) this sort of modification might be a problem?
推荐答案
它始终是安全的.正如规范所说的
It is always safe. As the spec says
如果存在"** identifier"形式,则将其初始化为新 接收任何多余的关键字参数的有序映射,默认为 一个新相同类型的空映射.
If the form "**identifier" is present, it is initialized to a new ordered mapping receiving any excess keyword arguments, defaulting to a new empty mapping of the same type.
重点已添加.
总是可以确保在可调用对象内获得一个新的映射对象.看到这个例子
You are always guaranteed to get a new mapping-object inside the callable. See this example
def f(**kwargs):
print((id(kwargs), kwargs))
kwargs = {'foo': 'bar'}
print(id(kwargs))
# 140185018984344
f(**kwargs)
# (140185036822856, {'foo': 'bar'})
因此,尽管f
可以修改通过**
传递的对象,但是它不能修改调用方的**
-对象本身.
So, although f
may modify an object that is passed via **
, it can't modify the caller's **
-object itself.
更新:由于您询问了一些极端情况,因此这里有一个特殊的地狱,它实际上会修改调用方的kwargs
:
Update: Since you asked about corner cases, here is a special hell for you that does in fact modify the caller's kwargs
:
def f(**kwargs):
kwargs['recursive!']['recursive!'] = 'Look ma, recursive!'
kwargs = {}
kwargs['recursive!'] = kwargs
f(**kwargs)
assert kwargs['recursive!'] == 'Look ma, recursive!'
不过,您可能不会在野外看到它.
This you probably won't see in the wild, though.
这篇关于修改** kwargs字典是否总是安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!