我正在构建一个使用属性链的 Python 类。我试图弄清楚是否有一种方法可以识别何时调用链的最终属性并在该点执行一些处理代码。调用最终链接属性后,我想处理收集的数据。我意识到可以在链的末尾显式调用处理属性,但我想尽可能避免这种情况。
例如:
o = ObjectInstance()
# Note that the attribute calling order is subjective
o('data').method_a('other data').method_c('other_data') #o.process() is called here automatically
--更新--
我找到了适合我的情况的解决方法,但它没有回答根本问题。
对于我的特殊情况,我打算使用单个实例分别处理多个链。通过重写我的类的 __call__ 属性,我可以检查是否已经处理了前面的链,并做出相应的 react 。我已经计划有一个单独的渲染方法——它也可以处理前面的链——在处理完所有链之后,所以它适用于我的特定场景。
这个类看起来像这样:
class Chainable:
current_chain_data = None
processed_chains = list()
def __call__(self, data):
if self.current_chain_data:
self.process()
#Some logic
self.current_chain_data = data
return self
def method_a(self, data):
#Some logic
self.current_chain_data = data
return self
def method_b(self, data):
#...
def process(self, data):
#do stuff
self.processed_chains.append(self.current_chain_data)
self.current_chain_data = None
def render(self):
if self.current_chain_data:
self.process()
for c in self.processed_chains:
output += c
return output
并像这样使用:
c = Chainable()
# do some chaining
c('data').method_a('other_data').method_c('other_data')
# previous chain is processed here, new chain started
c('additional_data').method_b('other_data') #...
# previous chain is processed here, output rendered
c.render()
请您参考如下方法:
无法识别“最后”调用,因为“链”不是语言构造,而是统一语法与您自己从非对象返回相同对象的(良好)实践相结合的结果-功能方法。
您的选择是:
- 按照您的建议进行最终流程调用(在许多方面是最干净的解决方案);
- 在每个阶段执行您的处理(这可能会或可能不会影响性能,具体取决于处理过程以及您的方法实际执行的操作);或
- 让每个方法都定义一个关键字参数,允许您将其标记为最终调用,以便触发处理。
我会建议选项 1,除非选项 2 自然不会产生性能损失,如果没有其他原因只是它引入了最少的复杂性,并且显式通常比隐式好。
您的覆盖解决方案 __call__有几个缺点:它可能会使您的用户感到困惑,因为它是不统一的;如果有人在 c 上调用另一个方法打电话前 c ,这种行为很可能会让他们感到惊讶(链继续);最后,你还需要一个 final render调用以关闭最后一个链,这将使此类代码比必要的更脆弱。
