Как определить метод, который будет действовать как декоратор для других методов внутри того же класса в Python? - PullRequest
0 голосов
/ 16 апреля 2020

Я создаю простую JSON БД, в которой есть такие методы, как insert, update, get и т. Д.

Я знаю, что просто создать метод self._write() для записи в json файл и вызовите его в каждом методе, но есть ли способ создать _write для декорации всех этих функций, , но как метод Database класса ?

Я попробовал это, но мне не удалось обернуть это вокруг:

import pathlib
import json

DATABASE_PATH = pathlib.Path('/home/me/db.json')


class Database:

    def __init__(self):
        self.data = dict()

    def _write(self):
        def decorator(f, *args, **kwargs):
            _response = f(**kwargs)  # I'm assuming this would be `insert` method call ?
            with DATABASE_PATH.open(mode='w', encoding='utf-8') as _db:
                json.dump(self.data, _db, indent=4)  # Calling `f` would modify `self.data`
            return _response

        return decorator

    @_write  # Complaining function `_write` lacks positional argument self, but can't access it ?
    def insert(self, **kwargs):
        if all(k for k in kwargs if k in ('name', 'surname')):  # Insert if contains all values.
            self.data.update(**kwargs)
            return True
        return False  # Insert failed.

Можно ли написать метод класса, который будет действовать как декоратор, который будет использоваться в других методах класса, определенных в того же класса?

1 Ответ

0 голосов
/ 25 апреля 2020

Мне удалось обойти эту проблему, но в конце я просто решил извлечь класс _write в качестве обычной функции декоратора.

Это решение нарушает многие правила Дзен из Python, если есть лучшее решение, я его приму:

import pathlib
import json

DATABASE_PATH = pathlib.Path('db.json')


class Database:

    def __init__(self):
        self.data = dict()

    def _write(fn):
        def decorator(self, **kwargs):
            _response = fn(self, **kwargs)
            with DATABASE_PATH.open(mode='w', encoding='utf-8') as _db:
                json.dump(self.data, _db, indent=4)
            return _response
        return decorator

    @_write
    def insert(self, **kwargs):
        if all(k for k in kwargs if k in ('name', 'surname')):  # Insert if contains all values.
            self.data.update(**kwargs)
            return True
        return False  # Insert failed.


if __name__ == '__main__':
    db = Database()
    db.insert(name='Dummy-Name', surname='Dummy-Surname')
...