Шаблон для ленивой загрузки с Python - PullRequest
2 голосов
/ 27 апреля 2011

У меня есть данные в форме dict (поступающие из базы данных MongoDB через PyMongo), например:

car = {_id: "1", "color": "silver", "steering_wheel":"2"}

, где значение "ering_wheel "- это идентификатор другого документа в моей базе данных, который представляетэкземпляр класса SteeringWheel.Загрузка из БД в Python приведет к:

steering_wheel = {_id: "2", "cover": "plastic"}

Для работы с данными я использую классы Python.Теперь мой вопрос о ленивой загрузке.Я могу думать о двух способах:

1) Сохранять ссылочный идентификатор и создавать другой атрибут только времени выполнения для прямого доступа к ссылочным объектам:

class Car(object):
    def __init__(self, _id, color, steering_wheel_ref_id, session):
        self._id = _id
        self.color = color
        self.steering_wheel_ref_id = steering_wheel_ref_id
        self.session = session

    @property
    def steering_wheel(self):
        try:
            return self.steering_wheel
        except AttributeError:
            # Get the referecend object from the session 
            self.steering_wheel = self.session.resolve_item_refs(self.steering_wheel_ref_id)
            return self.steering_wheel

2) Другой вариант - выполнитьпроверка типа:

class Car(object):
    def __init__(self, _id, color, steering_wheel, session):
        self._id = _id
        self.color = color
        self.steering_wheel = steering_wheel
        self.session = session

    @property
    def steering_wheel(self):
        if isinstance(self.steering_wheel, SteeringWheel):
            return self.steering_wheel
        else:
            # Get the referecend object from the session 
            self.steering_wheel = self.session.resolve_item_refs(self.steering_wheel_ref_id)
            return self.steering_wheel

Какой способ вы бы предпочли?Или есть лучшие способы / лучшие практики для разрешения доступа к ссылкам по идентификатору?

Ответы [ 4 ]

3 голосов
/ 27 апреля 2011

Как насчет этого?

class Car(object):
    def __init__(self, _id, color, steering_wheel_ref_id, session):
        self._id = _id
        self.color = color
        self.steering_wheel_ref_id = steering_wheel_ref_id
        self.session = session
        self._steering_wheel = None

    @property
    def steering_wheel(self):
        if self._steering_wheel is None:
            # Get the referecend object from the session 
            self._steering_wheel = self.session.resolve_item_refs(self.steering_wheel_ref_id)
        return self._steering_wheel
1 голос
/ 27 апреля 2011

Хотя в целом это EAFP, это не относится к случаям создания избыточности, IMO.

Итак:

@property
def steering_wheel(self):
if not hasattr(self, 'steering_wheel'):
    self.steering_wheel = self.session.resolve_item_refs(self.steering_wheel_ref_id)
    # And while we're at it, maybe a bit of housekeeping?
    del self.steering_wheel_ref_id
return self.steering_wheel

Говоря о избыточности ... если мы собираемся делать это много, возможно, нам следует инкапсулировать эту логику в свой собственный класс Proxy:

class DatabaseProxy(object):
    def __init__(self, session, id):
        self.session = session
        self.id = id

    def __getattr__(self, what):
        if what == 'value':
            self.value = self.session.resolve_item_refs(self.id) # cache for next time
            return self.value
        raise AttributeError

class Car(object):
    def __init__(self, _id, color, steering_wheel_ref_id, session):
        self._id = _id
        self.color = color
        self.steering_wheel_proxy = DatabaseProxy(session, steering_wheel_ref_id)
        self.session = session

    @property
    def steering_wheel(self): return self.steering_wheel_proxy.value

Что-то в этом роде.

1 голос
/ 27 апреля 2011

Если бы мне пришлось выбирать между одним из ваших двух подходов, я бы выбрал первый.Он более питоничен в том смысле, что вы используете типизацию утки, то есть «путь Питона».

Второй труднее читать и понимать.

Что касается других предложений, извинитено я ничего не получил: -)

0 голосов
/ 27 апреля 2011

Первый вариант, который использует типизацию утки и обработку исключений, является предпочтительным.Это следует методике «Проще просить прощения, чем разрешения» (также известной как EAFP), которую предпочитают в Python.

Отчасти это объясняется тем, что вместо вставки имени типа / класса в вашкод, вы просто пытаетесь выполнить операцию и обрабатываете ожидаемую ошибку.Это позволяет вам кодировать ПОВЕДЕНИЕ поверх ИДЕНТИЧНОСТИ.

Дополнительная информация:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...