清除嵌套函数调用

2024-04-26 10:20:33 发布

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

我写了几个函数,这些函数按顺序运行,每个函数都以前一个函数的输出作为输入,所以为了运行它,我必须运行这行代码

make_list(cleanup(get_text(get_page(URL))))

我发现这既丑陋又低效,有没有更好的方法来执行顺序函数调用?在


Tags: 方法函数代码texturlgetmake顺序
3条回答

实际上,这与任何重构常用的复杂表达式或语句的情况相同:只需将表达式或语句转换为函数即可。你的表达式恰好是一个函数调用的组合,这一点没有任何区别(但请参见下文)。在

因此,显而易见的是编写一个包装器函数,在一个地方将这些函数组合在一起,这样在其他任何地方都可以对包装器进行简单的调用:

def get_page_list(url):
    return make_list(cleanup(get_text(get_page(url))))

things = get_page_list(url)
stuff = get_page_list(another_url)
spam = get_page_list(eggs)

如果您不总是调用完全相同的函数链,则可以将其分解为您经常调用的部分。例如:

^{pr2}$

这种重构也打开了一扇大门,使代码更加冗长,但更易于调试,因为它只出现一次而不是多次:

^{3}$

如果您发现自己经常需要对组合函数进行这种重构,则可以编写一个生成重构函数的助手。例如:

def compose1(*funcs):
    @wraps(funcs[0])
    def composed(arg):
        for func in reversed(funcs):
            arg = func(arg)
        return arg
    return composed

get_page_list = compose1(make_list, cleanup, get_text, get_page)

如果您想要一个更复杂的compose函数(例如,允许传递多个参数/返回值),那么它的设计可能会有点复杂,因此您可能需要查看一下PyPI和ActiveState的各种现有实现。在

你可以试试这个。我总是喜欢分离火车残骸(书中的“干净代码”称这些嵌套函数为火车残骸)。这更易于阅读和调试。请记住,阅读代码的时间可能是编写代码的两倍,所以要使代码更易于阅读。你以后会感谢你自己的。在

url = get_page(URL)
url_text = get_text(url)
make_list(cleanup(url_text))

# you can also encapsulate that into its own function
def build_page_list_from_url(url):
    url = get_page(URL)
    url_text = get_text(url)
    return make_list(cleanup(url_text))

选项:

  1. 重构:将这一系列函数调用作为一个恰当命名的方法来实现。在
  2. 看看装修工。它们是以这种方式“链接”函数的语法糖。E、 实现cleanup和{}作为装饰器,然后用它们装饰{}。在
  3. 组合函数。请参阅this answer中的代码。在

相关问题 更多 >