Python - 链接方法:返回`self` vs返回一个新的克隆对象

时间:2013-06-03 17:11:02

标签: python django django-queryset

由于我正在进行的项目中存在一些限制,我不得不用自定义项替换Django的QuerySet类。 QuerySet对象可以将它们的方法链接起来(例如QuerySet().filter(...).exclude(...)等等),因此在我的实现中,每个方法都只返回self。所以我的班级看起来像这样:

class MyQuerySet:
    ...
    def filter(self, *args, **kwargs):
        # Do some stuff and then:
        return self

这样我就模仿了Django的QuerySet行为。

然而,看着Django代码,我注意到,QuerySet的方法不是返回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

所以基本上,每次调用一个方法时,QuerySet都会克隆自己,实例化一个新对象并返回它。

我的问题是:为什么?我的方式错了吗? 我担心的是我这样做的方式,有些东西可能会破裂,否则我无法解释为什么Django团队会做它所做的事情。

1 个答案:

答案 0 :(得分:2)

Django执行此操作,以便可以保留基本查询并重复使用,而无需继承未来" child"查询,就像exclude()上的filter()一样。我猜测有人试图为以后存储查询,并意识到没有复制就没有用。

我克隆了django repo并在git log上快速django/db/models/query.py,搜索了短语clone

引入此更改的补丁如下:

https://github.com/django/django/commit/d4a3a4b