Is it always safe to modify the `**kwargs` dictionary?

后端 未结 3 796
刺人心
刺人心 2021-01-31 13:45

Using the Python function syntax def f(**kwargs), in the function a keyword argument dictionary kwargs is created, and dictionaries are mutable, so the

3条回答
  •  鱼传尺愫
    2021-01-31 14:46

    It is always safe. As the spec says

    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.

    Emphasis added.

    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'})
    

    So, although f may modify an object that is passed via **, it can't modify the caller's **-object itself.


    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.

提交回复
热议问题