Из-за некоторых ограничений в проекте, над которым я работаю, мне пришлось заменить класс QuerySet Django на пользовательский. Объекты QuerySet могут иметь свои методы прикованным (например, QuerySet().filter(...).exclude(...)
и т. Д.), Поэтому в моей реализации каждый метод просто возвращает self
. Поэтому мой класс выглядит следующим образом:Python - Цепочные методы: возврат `self` против возврата нового клонированного объекта
class MyQuerySet:
...
def filter(self, *args, **kwargs):
# Do some stuff and then:
return self
Таким образом, я подражал поведению QuerySet Django.
Однако, глядя на код Django, я заметил, что вместо того, чтобы возвращать self
, методы QuerySet возвращают клонированный объект при каждом вызове. Похоже, что этот (Удалены ненужные вещи):
class QuerySet(...):
...
def filter(self, *args, **kwargs):
clone = self._clone()
# Do some stuff and then
return clone
def _clone(self,...):
klass = self.__class__
obj = klass(...)
return obj
Так в основном, каждый раз, когда вызывается метод, QuerySet клонирует себя, создавать новый объект и вернуть его.
Мой вопрос: ПОЧЕМУ? Я ошибаюсь?
Мой страх в том, что так, как я это делаю, что-то может сломаться, иначе я не могу объяснить, почему команда Django сделала то, что сделала.
Возвращение клонированный объект означает, что исходный объект гарантированно неизменность (вы изменяете клон, а не исходный объект). Это только наблюдение с моей стороны. –
@RobertHarvey - Кажется очень действительным, глядя на объяснение здесь: https://docs.djangoproject.com/en/1.0/ref/models/querysets/#all – karthikr
Я смотрю вывод 'git blame' для этого файла , и я вижу 'self._clone()', исходящий из нескольких коммитов. Какова бы ни была причина, этот дизайн был реализован последовательно на некоторое время. https://github.com/django/django/blame/master/django/db/models/query.py – jpaugh