Как добавить метод в dict используя декоратор? - PullRequest
0 голосов
/ 14 декабря 2018

То, что я хочу, это что-то вроде регистра маршрутизации фляги:

class ClassName(object):
    def __init__(self):
        self.handle_dict = {}

    def handle(data):
        h = self.handle_dict.get(data)
        h()

    @handle_route("open")
    def open_handle()
        """do something"""
        pass

    @handle_route("close")
    def close_handle()
        """do something"""
        pass


    def handle_route()
        """How to implement this warpper?"""

Я знаю, что мог бы написать дикт в функции __init__:

self.handle_dict ={"open": self.open_handle, "close": self.colse_handle}

Но способ декорации выглядит более понятным, верно?

Я пробовал

def handle_router(self, path):
    def warpper(f):
        self.handle_map[path] = f
        return f
    return warpper

но self недопустимо в аргументах декоратора, @handle_router(self, "path") недопустимо.

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Вместо того, чтобы украшать функции, вы можете просто использовать согласованное соглашение об именах:

class ClassName(object):
    def handle(self, type):
        getattr(self, '{}_handle'.format(type))()

    def open_handle(self):
        print('open_handle')

    def close_handle(self):
        print('close_handle')


ClassName().handle('open')

>>> open_handle
0 голосов
/ 14 декабря 2018

Фактически, дескриптор dict должен быть своего рода атрибутом класса, так как он заполняется во время определения класса, и все экземпляры совместно используют одно и то же отображение обработчика маршрута.Однако класс еще не существует, когда декоратор вызывается и оценивается.Вы могли бы сделать что-то вроде следующего:

from functools import partial

class A:
    router = {}

    def handle(self, data):
        m = self.router.get(data)
        return m(self)

    @partial(router.setdefault, 'open')
    def open_handle(self):
        return 5

>>> a = A()
>>> a.handle('open')
5

Или быть более явным и извлечь функцию маршрутизацииailail в повторно используемый класс:

from functools import partial

class Router(dict):
    __call__ = lambda self, route: partial(self.setdefault, route)

class A:
    router = Router()

    def handle(self, data):
        m = self.router.get(data)
        return m(self)

    @router('open')
    def open_handle(self):
        return 5
...