Initialising in Python using Keyword Args without

2019-08-06 13:43发布

问题:

How can I use keyword args in an initialiser without sharing it between instances of a class?

Example of the bad behaviour below, if I were to add anything to the set foo then it would be added in both instances.

In [1]: class Klass:
    def __init__(self, foo=set()):
        self.foo = foo
In [2]: a = Klass()
In [3]: b = Klass()
In [4]: a.foo is b.foo
Out[4]: True

回答1:

Note that this issue will only occur with mutable default arguments - see "Least Astonishment" and the Mutable Default Argument. To use a mutable default argument, it is conventional to set the default to None in the function definition, then check inside the function whether or not a value has been supplied:

class Klass:

    def __init__(self, foo=None):
        if foo is None:
            foo = set()
        self.foo = foo

or:

self.foo = foo if foo is not None else set()

Note that None is tested by identity (if foo is None:), not equality (if foo == None:) or truthiness (if not foo:). For example, the latter is an issue if you want to explicitly pass in an empty set you have referenced elsewere.