def at_time(time_of_day, _actions={}):
    def decorator(func):
        def wrapper(self, time_of_day):
            for cls in type(self).__mro__:
                if func := _actions.get((f'{cls.__qualname__}.{name}', time_of_day)):
                    return func(self)
            raise ValueError(f'No {name} found in the {time_of_day} time')
        name = func.__name__
        _actions[func.__qualname__, time_of_day] = func
        return wrapper
    return decorator

class PersonalChef():
    @at_time('morning')
    def cook(self):
        print("Cooking breakfast")

    @at_time('evening')
    def cook(self):
        print("Cooking dinner")

class PersonalChefUK(PersonalChef):
    @at_time('evening')
    def cook(self):
        print("Cooking supper")

PersonalChef().cook('morning')
PersonalChef().cook('evening')
PersonalChefUK().cook('morning')
PersonalChefUK().cook('evening')