Decorated method loses 'self' context, when called

Viewed 47

I have EventPull class to register callback for some event:

class EventPull:
    _events: dict[int, Event] = dict()

    @classmethod
    def register(cls, event_type: int, *callbacks: CallbackType):
        event = cls._events.setdefault(event_type, Event(event_type))
        event.add(*callbacks)

    @classmethod
    def dregister(cls, event_type: int):
        def decorator(callback):
            cls.register(event_type, callback)
            return callback

        return decorator

Event class:

class Event:
    type: int
    _callbacks: set[CallbackType]

    def __init__(self, type: int, *callbacks: CallbackType) -> None:
        self.type = type
        self._callbacks = set(callbacks)

    def emit(self, event: pygame.event.Event):
        for callback in self._callbacks:
            callback(self, event) # calling registered callbacks

    def add(self, *callbacks: CallbackType):
        self._callbacks.update(callbacks)

Registering without using decorator working as expected:

class Game:
    def __init__(self) -> None:
        EventPull.register(pygame.QUIT, self.stop)

   def stop(self, *_):
       print('call', self, *_) # here 3 arguments and 'self' is object of Game type
       self.running = False

But when I trying to register it with decorator, the 'self' argument of 'stop' method isn't a Game object:

class Game:

    def __init__(self) -> None:
        # EventPull.register(pygame.QUIT, self.stop)

    @EventPull.dregister(pygame.QUIT)
    def stop(self, *_):
        print('call', self, *_) # now 2 arguments and 'self' is object of Event type
        self.running = False

Why it's loses context in this case? How can i fix it?

0 Answers
Related