Python:dosomethinghere().dependent().on().thismethod()?

2024-04-27 05:21:45 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我编写这样的代码,我可以将对象实例上的方法调用链接在一起:

class ChainClassTest(object):
    def order_by(self, *args, **kwargs):
        print("I'm in order_by")
        return self

    def filter_by(self, *args, **kwargs):
        print("I'm in filter_by")
        return self

    def get_list(self, *args, **kwargs):
        print("I'm in get_list")
        return self


if __name__ == "__main__":
    cct = ChainClassTest()
    cct.get_list().filter_by().order_by()

但是我希望能够让get_list()调用根据order_by设置的值执行一些操作。当然,在执行order_by的时候get_list已经完成了执行,所以我不能这样做。或者我可以吗?你知道吗

我考虑过使用get_listfilter_byorder_by和其他类似的方法来更新一堆函数调用,然后在最后执行它们。。。当然,除了没有办法知道你已经走到了尽头。你知道吗

这将允许这种情况发生

cct.get_list().filter_by().order_by()
cct.now_actually_do_it()

其中now_actually_do_it消耗了前一行代码创建的函数堆栈,但我真的希望能够在一行中完成这项工作。你知道吗


编辑1:为了清楚起见,我只提到了now_actually_do_it作为如何完成的指示,但我真的不想这样做。你知道吗


Tags: inselfgetbyreturndefargsorder
2条回答

在这种情况下,您希望有一个链式调用类型,但是不能返回self,因为order_by()不会作用于filter_by()正在创建的过滤结果集,而是作用于原始的cct对象。你知道吗

相反,每个方法都应该返回一个结果集,该结果集还包含用于添加过滤等的方法

另一方面,Python已经为其中大部分内置了:

filter(filter_fun, sorted(cct.get_list(), key=keyfun))

因此,这样做的唯一原因是,如果您实际构建的查询被延迟到对库的调用或服务调用,就像ORM一样。在这种情况下,您应该构建一个包含过滤和排序命令的对象链并返回它,然后在调用时解析和执行该链。你知道吗

在上述函数中返回self在任何情况下都没有什么用处。你知道吗

当然,除非您在每个调用中实际修改self,但如果您这样做,您的链式调用API将很混乱。改变自我意志 表示对象保留的状态不是对象的一部分,而是调用的一部分。例如,您可以让.filter_by()在对象上设置一个过滤器,由.get_list()使用。但在创建新的.get_list()之前,必须重置该筛选器,否则该筛选器仍将处于活动状态。你知道吗

很难使用而且易碎。你知道吗

您可以实现__iter__方法。你知道吗

class ChainClassTest(object):

    ...

    def __iter__(self):
        for i in self.now_actually_do_it():
            yield i

通过这种方式,您可以执行以下操作:

>>> my_list = list(cct.filter_by().order_by())

以及

>>> for item in cct.filter_by().order_by():
...    print item

等等

您还可以实现:
__len__(self)支持len(cct.filter_by().order_by())
__getitem__(self,item)支持cct.filter_by().order_by()[34]。你知道吗

相关问题 更多 >