1

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
0

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Is there a stylistic reason to not inline the foo = set() with the if?
@BookOfGreg per the style guide, "Compound statements (multiple statements on the same line) are generally discouraged.", although it subsequently adds "...sometimes it's okay to put an if/for/while with a small body on the same line"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.