Мне очень интересно, как SQLAlchemy создает строки запроса, например:
(Session.query(model.User)
.filter(model.User.age > 18)
.order_by(model.User.age)
.all())
Насколько я вижу, там применялся какой-то шаблон прокси. В моем небольшом проекте мне нужно сделать аналогичную конструкцию строки, используя подход ООП. Итак, я попытался воссоздать это поведение.
Во-первых, какой-то объект, один из множества подобных объектов:
class SomeObject(object):
items = None
def __init__(self):
self.items = []
def __call__(self):
return ' '.join(self.items) if self.items is not None else ''
def a(self):
self.items.append('a')
return self
def b(self):
self.items.append('b')
return self
Все методы этого объекта возвращают self, поэтому я могу вызывать их в любом порядке и неограниченное количество раз.
Во-вторых, прокси-объект, который будет вызывать методы субъекта, если это не метод perform, который вызывает объект для просмотра результирующей строки.
import operator
class Proxy(object):
def __init__(self, some_object):
self.some_object = some_object
def __getattr__(self, name):
self.method = operator.methodcaller(name)
return self
def __call__(self, *args, **kw):
self.some_object = self.method(self.some_object, *args, **kw)
return self
def perform(self):
return self.some_object()
И наконец:
>>> obj = SomeObject()
>>> p = Proxy(obj)
>>> print p.a().a().b().perform()
a a b
Что вы можете сказать об этой реализации? Существуют ли более эффективные способы создания желаемого количества классов, которые бы создавали такую строку с одним и тем же синтаксисом?
PS: Извините за мой английский, это не мой основной язык.