Украсить класс для запуска фрагмента кода при вызове __get __ () - PullRequest
1 голос
/ 13 апреля 2020

Пожалуйста, посмотрите на приведенный ниже код

class MyStudent:
    def __init__(self, student_id, student_name):
        self._student_id = student_id
        self._student_name = student_name

    def get_student_id(self):
        return self._student_id

    def get_student_name(self):
        return self._student_name


student1 = MyStudent(student_id=123, student_name="ABC")
student1.get_student_id()
student1.get_student_name()

Я хотел бы запустить некоторый код, например, добавить студента в БД всякий раз, когда вызывается student1.get_student_id() или student1.get_student_name() (или когда Доступ к get (). Пожалуйста, исправьте меня, если я использовал неправильный дескриптор). И я должен делать это через декораторы только для нескольких классов, как показано ниже

@save_student_to_db
class MyStudent:......

Как этого можно добиться с помощью декораторов? Мне нужно использовать один декоратор для нескольких классов, которые могут иметь любой метод. Всякий раз, когда любой метод (кроме тех, которые начинаются с _ или __) любого класса вызывается, декоратор должен сохранять данные в DB

1 Ответ

1 голос
/ 13 апреля 2020

Если все классы реализуют одни и те же методы, скажем, get_student_id и get_student_name, и имеют одинаковые атрибуты, скажем, _student_id и _student_name, то вы можете создать декоратор классов следующим образом:

from functools import wraps
from somewhere import Database

@wraps(fn)
def _method_decorator(fn):
    def getter_wrapper(self):
        db = Database()
        db.save(self._student_id, self._student_name)
        return fn(self)
    return getter_wrapper

def save_student_to_db(cls):
    cls.get_student_id = _method_decorator(cls.get_student_id)
    cls.get_student_name = _method_decorator(cls.get_student_name)
    return cls

Что касается базы данных, вы можете создавать ее экземпляры каждый раз, когда это необходимо, как я предлагал выше, или сделать это для вас. Я уже некоторое время пользуюсь инъекционным , и он довольно простой и в то же время мощный, но есть сыворотка .

...