Search code examples
pythonpython-3.xfunctionclassinit

Creating a class instance as a default argument inside itself


I've made a function inside a class with an argument I want that argument to default to becoming an instance of the class if not specified.

here's what I assumed would work:

class Agent:
    def __init__(self, value = dict):
        self.value = value

    def arbitrary(self, other_instance = self.__class__({})):
        print(other_instance.value.get('placeholder', 0))

However, it claims self is not defined. Theoretically, I could simply just do

    def arbitrary(self, other_instance = None):
        if other_instance is None:
            other_instance = self.__class__({})
        print(other_instance.value.get('placeholder', 0))

however that's pretty cobbled together, so I wanted to know if there was a way to do it within the argument default before I resort to something like that.


Solution

  • There's probably a better solution to your actual problem, but since you're not sharing those details, it's hard to say what exactly.

    However, for the example you're giving, in case other_instance would be None, value would be an empty dict, and thus the call to .get() can only return 0.

    So, this is equivalent:

        def arbitrary(self, other_instance = None):
            if other_instance is None:
                print(0)
            else:
                print(other_instance.value.get('placeholder', 0))
    

    Which avoids the construction of a throwaway instance altogether.

    Your actual use case may have a bit more going on, but it's likely there's a better solution than on-the-fly creation of an empty instance as well. If there's not, the solution you have with None is the expected way to do it.

    (Note: setting value to dict in the constructor in the first example actually sets it to the type, not an empty instance, which is probably what you intended - however, doing so would cause warnings about a mutable default, and the correct solution there is to use None and initialisation in the body as well)

    Edit: in the comments you indicated that you set value to dict to signal what type is needed - however, this has the unwanted side effect that some IDEs will infer that the type of value is type or Any, which it isn't. Instead, use this:

    from typing import Optional
    
    
    class ClassName:
        def arbitrary(self, other_instance: Optional[dict] = None):
            if other_instance is None:
                print(0)
            else:
                print(other_instance.value.get('placeholder', 0))