Python:dosomethinghere().dependent().on().thismethod()?
如果我编写这样的代码,我可以将对象实例上的方法调用链接在一起:Python:dosomethinghere().dependent().on().thismethod()?,python,python-3.x,python-2.x,Python,Python 3.x,Python 2.x,如果我编写这样的代码,我可以将对象实例上的方法调用链接在一起: 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 se
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\u list()
调用根据order\u by
设置的值执行某些操作。当然,在执行order\u by
时,get\u list
已经完成了执行,所以我不能这样做。或者我可以吗
我考虑过使用get_list
、filter_by
、order_by
和其他类似的方法来更新函数调用堆栈,然后在最后执行它们。。。当然,除了没有办法知道你已经走到了尽头
这将允许这种情况发生
cct.get_list().filter_by().order_by()
cct.now_actually_do_it()
其中now\u实际上\u do\u it
消耗了前一行代码创建的函数堆栈,但我真的希望能够在一行中完成这项工作
编辑1:为了清楚起见,我只提到了
现在实际上做了它,作为如何做的指示,但我真的不想这样做。在这种情况下,您希望有一个链接类型的调用,但是您不能返回self
,因为order\u by()
不作用于filter\u by()
创建的过滤结果集,但作用于原始cct
对象
相反,每个方法都应该返回一个结果集,该结果集还具有用于添加过滤等的方法
另一方面,Python已经为其中的大部分内置了:
filter(filter_fun, sorted(cct.get_list(), key=keyfun))
因此,这样做的唯一原因是,如果您实际构建的查询被延迟到对库的调用或服务调用,就像ORM一样。在这种情况下,您应该构建一个包含过滤和排序命令的对象链并返回它,然后在调用时解析和执行该链
在上述函数中返回self
,在任何情况下都没有什么用处
当然,除非您在每次调用中都实际修改了self,但如果您这样做,您的链接调用API将很混乱。修改自我意志也是如此
表示对象保留的状态不是对象的一部分,而是调用的一部分。例如,您可以让.filter\u by()
在对象上设置一个过滤器,该过滤器由.get\u list()
使用。但是,在创建新的.get_list()
之前,必须重置该筛选器,否则该筛选器仍将处于活动状态
这很难使用,也很脆弱。您可以实现方法
class ChainClassTest(object):
...
def __iter__(self):
for i in self.now_actually_do_it():
yield i
这样,您就可以执行以下操作:
>>> my_list = list(cct.filter_by().order_by())
及
等等
您还可以实现:
\uuuu len(self)
支持len(cct.filter\u by().order\u by())
\uu getitem(self,item)
支持cct.filter\u by().order\u by()[34]
如果您想实现,您不会返回self
,而是返回某种类型的StatementBuilder实例,该实例收集所有参数,直到您现在才真正执行它。
。您不只是以不同的顺序调用它吗cct.filter\u by().order\u by().get\u list()
。让get_list
返回一个列表而不是self。将其作为任何链接的结尾。如果将actuallydoit方法附加到链的结尾,会不会有什么不好的结果?这是一种非常流行的模式。否则,您将不得不对代码进行初步检查,这将超出纯python的范围。不确定您要问什么,因为您还没有回答自己。不能让较早的方法调用依赖于较晚的方法调用。您可以将所有调用堆积到一个堆栈中,然后执行一个“finish”操作来解析所有调用,但如果没有一个明确的“finish”,您就无法做到这一点,原因正是您提到的:方法无法知道它是否是链中的最后一个。(不过,“finish”不需要单独的一行;您可以执行obj.a().b().c().finish()
)这是一种典型的ORM实现模式,用于链接和“建立状态”。也称为延迟加载/评估,它仍然在之前执行。get\u list()
。filter\u by()
。由于计算是惰性的,您可以让.filter\u by()
在self
上设置一个过滤器,该过滤器由使用。get\u list()
,但在再次调用.get\u list()
之前,您必须重置该过滤器。对象将保留一个状态,该状态只应是方法调用的一部分。这是糟糕的设计,会导致麻烦。get\u list
是我的错误,我的意思是你不需要它,你可以把iys逻辑放在\u iter\u
中。我修复了我的答案。无论调用什么函数,我的注释仍然有效。;-)因此,我不确定我是否理解您的意思,OP希望filter\u by()
更改对象行为
>>> for item in cct.filter_by().order_by():
... print item