Python 3控制脚本中的流程,包含许多步骤

时间:2016-01-09 08:23:54

标签: python syntax control-flow

我正在用Python写一个算法(学习它只是为了写这个算法),我把它分成小块或模块,这是可以理解的。

在Python中,是否有一种干净的方式来运行一组函数,最后一次传入前一个值?

我现在有这个,但是可能会有十几个步骤使这看起来像一个巨大的金字塔而且:

calculate_excess_returns(
    calculate_returns(
        get_monthly_historical_returns('./assets/monthly_historical_returns.csv')
    )
)

我也可以这样做,但我发现它的可读性较低:

monthly_historical_returns = get_monthly_historical_returns('./assets/monthly_historical_returns.csv')
calculated_returns = calculate_returns(monthly_historical_returns)
calculated_excess_returns = calculate_excess_returns(calculated_returns)

在JavaScript中,我们有一个称为" promises"的通用控制流程。看起来像这样:

getJSON('story.json')
  .then(function(story) {
    return getJSON(story.chapterUrls[0]);
  }).then(function(chapter1) {
    console.log("Got chapter 1!", chapter1);
  });

你可以看到他们在结果传递结果时很容易遵循流程:故事的getJSON然后第一章的getJSON然后告诉用户他们到了第1章。

在我的算法脚本中做得很好,能够做类似的事情:

   SomeModuleOrPackage
    .startWith(get_monthly_historical_returns('./assets/monthly_historical_returns.csv'))
    .then(calculate_returns)
    .then(calculate_excess_returns)

只是非常清楚每个步骤是什么。也许某些函数数组循环并以某种方式将值传递给下一个?

2 个答案:

答案 0 :(得分:3)

基本上,你想要一种更好看的方式来组合函数。我建议您使用一些函数式编程包,例如funcyfn。这是一个利用第一个包的例子。

import funcy


pipeline = funcy.rcompose(
    get_monthly_historical_returns,
    calculate_returns,
    calculate_excess_returns
)

result = pipeline('./assets/monthly_historical_returns.csv')

或者,如果您不打算多次使用管道,您可以立即计算结果:

result = funcy.rcompose(
    get_monthly_historical_returns,
    calculate_returns,
    calculate_excess_returns
)('./assets/monthly_historical_returns.csv')

这些功能从左到右执行。一个函数的输出作为第一个参数传递给下一个函数。如果函数需要多个参数,则可以使用标准库中的functools.partial为函数提供额外的参数。

import funcy
from functools import partial 


composition = funcy.rcompose(
    partial(func1, additional_arg_name=something),
    ...
)

我想你明白了。关于您的getJSON示例,您可以将匿名函数(lambda)传递给rcompose,以使代码与您的JavaScript示例几乎完全相同。

您可以通过pip:pip install funcy

安装软件包

答案 1 :(得分:1)

您可以将它们放入listtuple并循环播放:

var = './assets/monthly_historical_returns.csv'
for func in (get_monthly_historical_returns,
             calculate_returns,
             calculate_excess_returns):
    var = func(var)