A causa di alcune restrizioni in un progetto su cui sto lavorando, ho dovuto sostituire la classe QuerySet di Django con una personalizzata. Gli oggetti QuerySet possono avere i loro metodi concatenati (ad esempio QuerySet().filter(...).exclude(...)
e così via), quindi nella mia implementazione, ogni metodo restituisce semplicemente self
. Quindi la mia classe ha questo aspetto:Python - Metodi concatenamento: restituire `self` e restituire un nuovo oggetto clonato
class MyQuerySet:
...
def filter(self, *args, **kwargs):
# Do some stuff and then:
return self
In questo modo ho imitato il comportamento di QuerySet di Django.
Tuttavia, guardando il codice Django, ho notato che invece di tornare self
, i metodi di set di query restituiscono un oggetto clonato ogni volta che vengono chiamati. Sembra che questo (cose inutili rimosso):
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
Quindi, in pratica, ogni volta che un metodo viene chiamato, QuerySet sarà clonare se stessa, un'istanza di un nuovo oggetto e restituirlo.
La mia domanda è: PERCHÉ? La mia strada è sbagliata?
La mia paura è che il modo in cui lo faccio, qualcosa potrebbe rompersi, altrimenti non posso spiegare perché il team Django ha fatto quello che ha fatto.
Restituzione di un oggetto clonato significa che l'oggetto originale è garantita immutabilità (Stai cambiando il clone, non l'oggetto originale). Questa è solo un'osservazione da parte mia, però. –
@RobertHarvey - Sembra molto valido, guardando la spiegazione qui: https://docs.djangoproject.com/en/1.0/ref/models/querysets/#all – karthikr
Sto guardando l'output di 'git blame' per quel file e vedo 'self._clone()' proveniente da diversi commit. Qualunque sia la ragione, questo progetto è stato implementato in modo coerente per un po 'di tempo. https://github.com/django/django/blame/master/django/db/models/query.py – jpaugh