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

后端 未结 3 791
刺人心
刺人心 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:37

    Both of above answers are correct in stating that technically, mutating kwargs will never have an effect on the parent scopes.

    But... that's not the end of the story. It is possible for a reference to kwargs to be shared outside of the function scope, and then you run into all the usual shared mutated state problems that you'd expect.

    def create_classes(**kwargs):
    
        class Class1:
            def __init__(self):
                self.options = kwargs
    
        class Class2:
            def __init__(self):
                self.options = kwargs
    
        return (Class1, Class2)
    
    Class1, Class2 = create_classes(a=1, b=2)
    
    a = Class1()
    b = Class2()
    
    a.options['c'] = 3
    
    print(b.options)
    # {'a': 1, 'b': 2, 'c': 3}
    # other class's options are mutated because we forgot to copy kwargs
    

    Technically this answers your question, since sharing a reference to mutable kwargs does lead to effects outside of the function scope's.

    I've been bitten multiple times by this in production code, and it's something that I explicitly watch out for now, both in my own code and when reviewing others. The mistake is obvious in my contrived example above, but it's much sneakier in real code when creating factory funcs that share some common options.

提交回复
热议问题