'Any workaround to pass multiple arguments to defaultdict's default_factory?

I have a factory method called create_food, which takes in multiple string parameters like below:

def create_food(self, meat: str, vege: str) -> str:

I have another dictionary called __kitchen which uses string as key & value like below:

self.__kitchen: dict[str, str] = dict()

The __kitchen dictionary would take a dish name as a key value. If the dish name is not found, then it would call create_food, then add the food to the dictionary using the dish name as its key.

    food: str = self.__kitchen.get(dish)
    
    if food is None:
        food = self.create_food('ham', 'egg')
        self.__kitchen[dish] = food
    
    return self.__kitchen[dish]

Now, I would like to use defaultdict & override its __missing__ method by using create_food. However, I could not find a way to pass in extra parameters like meat, vege.

class KitchenDefaultDict(defaultdict):
    def __init__(self, factory: callable):
        super().__init__(factory)

    def __missing__(self, key):
        if self.default_factory is None:
            raise TypeError(self.default_factory)

        food: str
        food = self[key] = self.default_factory()  # how to pass meat, vege?
        return food

I am aware that default_factory in defaultdict does not take any argument at all. Is there any workaround to pass extra arguments to default_factory? Any advice & solution is welcomed.



Solution 1:[1]

What would you pass? key is the dish, which is distinct from the ingredients.

What you can do is instantiate a defaultdict with a function that calls create_food with default arguments

self.__kitchen = defaultdict(lambda: self.create_food('ham', 'egg'))

If you instead want to pass key to the default factory, I wouldn't subclass defaultdict, but instead subclass dict.

class factorydict(dict):
    def __init__(self, factory: callable):
        self.factory = factory

    def __missing__(self, key):
        if self.factory is None:
            raise KeyError(key)

        value = self.factory(key)
        self[key] = value
        return value

and then instantiate __kitchen with one of those

self.__kitchen = factorydict(lambda dish: self.__create_dish(dish)) // or whatever

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1