[Python] How to reference class static data in decorator method

Discussão em 'Python' iniciado por Stack, Março 17, 2025.

  1. Stack

    Stack Membro Participativo

    Is it possible to make the global variable handlers a static class variable?

    from typing import Callable, Self

    # dispatch table with name to method mapping
    handlers:dict[str, Callable[..., None]] = {}

    class Foo:
    # Mark method as a handler for a provided request name
    @staticmethod
    def handler(name: str) -> Callable[[Callable], Callable]:
    def add_handler(func: Callable[..., None]) -> Callable:
    handlers[name] = func # This line is the problem
    return func
    return add_handler

    # This method will handle request "a"
    @handler("a")
    def handle_a(self) -> None:
    pass

    # Handle one request with provided name, using dispatch table to determine method to call
    def handle(self, name: str) -> None:
    handlers[name](self)


    The goal is to have the decorator add the decorated method into a dict that is part of the class. The dict can then be used to dispatch methods via the name used in request messages it will receive.

    The problem seems to be how to refer to class data inside a decorator.

    Of course using self.handlers won't work, as self isn't defined. The decorator is called when the class is defined and there aren't any instances of the class created yet for self to reference.

    Using Foo.handlers doesn't work either, as the class name isn't defined until after the class definition is finished.

    If this wasn't a decorator, then handler() could be defined as a @classmethod, and then the class would be the first argument to the method. But it doesn't appear possible to make a decorator a class method.

    An example of how this might be used, would be as a handler for a server requests, e.g. a websocket server:

    from websockets.sync.server import serve
    def wshandler(websocket):
    f = Foo() # Create object to handle all requests
    for msg in websocket:
    decoded = json.loads(msg)
    # Decoded message will have a field named 'type', which is a string indicating the request type.
    Foo.handler(decoded['type'])

    with serve(wshandler, "localhost", 8888) as server:
    server.serve_forever()

    Continue reading...

Compartilhe esta Página