私が進めているプロジェクトのいくつかの制約のため、DjangoのQuerySetクラスをカスタムクラスに置き換えなければなりませんでした。 QuerySetオブジェクトはメソッドをチェーンにすることができます(例えばQuerySet().filter(...).exclude(...)
など)。私の実装では、すべてのメソッドが単にself
を返します。だから私のクラスには、次のようになります。Python - チェーンメソッド: `self`を返すことと新しいクローンオブジェクトを返すこと
class MyQuerySet:
...
def filter(self, *args, **kwargs):
# Do some stuff and then:
return self
この方法で私は、Djangoのクエリセットの動作を真似しました。しかし
は、Djangoのコードを見て、私の代わりにself
を返す、クエリセットのメソッドは、クローン化されたオブジェクト、それらが呼び出されるたびに返すことに気づきました。
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
だから、基本的には、メソッドが呼び出されるたびに、クエリセットは、自身のクローンを作成し、新しいオブジェクトをインスタンス化し、それを返します。それは、この(削除不要なもの)のように見えます。
私の質問は:なぜですか?私の方法は間違っていますか?
私の恐怖は、私がそれをやっていることです、何かが壊れるかもしれない、そうでなければ私は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