修改** kwargs字典是否总是安全的? [英] Is it always safe to modify the `**kwargs` dictionary?

查看:83
本文介绍了修改** kwargs字典是否总是安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆