【问题标题】:Is it possible to use too many functions in Python?是否可以在 Python 中使用太多函数?
【发布时间】:2012-12-11 20:57:06
【问题描述】:

这是一个宽泛的问题。

当我发现自己不得不编写越来越长的脚本时,我发现我的本能是将所有内容分解成一口大小的函数;但是,这最终会导致函数调用函数调用函数调用函数....我想知道我是否完全以错误的方式思考这个问题。

这是一个删节脚本的样子。抱歉,这有点做作。

def simple_task_1():
    return

def simple_task_2():
    return

def simple_task_3():
    return

def simple_task_4():
    return

def complex_task_1():
    simple_task_2()
    simple_task_3()
    simple_task_4()
    return

def startup():
    simple_task_1()
    complex_task_1()
    simple_task_4()

def finish():
    # other function calls
    return

def main():
    startup()
    finish()

那么,这是使用函数的正确方法吗?有没有一个客观的观点,你可以说你在彼此内部进行了太多的函数调用?我是否应该为最终只完成一次的任务创建函数?

【问题讨论】:

  • 最终,您会希望将相关函数组分组或封装到类中。该类还将包含函数之间的任何共享状态(现在称为方法)。
  • @Keith -- 我同意你的说法,但是,为了澄清,我认为重要的是要提到没有状态共享的类是没有意义的。在这种情况下,具有功能的模块可能会更好。换句话说,如果你的每个类的方法都可以用@staticmethod 装饰,那么你可能实际上并不想要一个类。

标签: python


【解决方案1】:

Python 有一个“递归”限制。如果你做到了,那么你可能使用了太多的函数,否则这可能没什么大不了的——通常你只能在递归调用函数时达到递归限制(然后通常 因为你做错了什么,但没有在你应该做的时候打破)。

函数的意义在于让您的生活更轻松。如果你发现你有太多的功能并且你实际上并没有让你的生活更轻松,那么这可能是一个问题。例如:

def add(x,y):
    return x+y

这是一个毫无意义的函数,最好避免使用,但是,如果你想要sinc

def sinc(x):
    return math.sin(x)/x

这实际上可能很有用,因为新函数名称比其中执行的代码更具描述性。另外,稍后如果您发现需要移除 x=0 处的奇点,您可以轻松地将其添加到 sinc

最终,可读性才是最重要的。如果使用函数使您的代码更易于阅读,那么它可能是值得的(即使您只从一个地方调用它并且可以轻松地内联它)。如果您真的关心性能,则存在一些灰色区域(函数的执行时间确实比内联代码要长一些),但是您不应该以此为借口来内联难以阅读的内容,除非您可以可靠地证明这是一个性能瓶颈。

【讨论】:

  • 谢谢!我喜欢所有的答案,但你的答案特别为我澄清了。
  • 请注意,最大堆栈深度非常小,限制了递归函数的使用方式。
【解决方案2】:

将大事物分解成小事物,无论是模块、类、函数等,这正是处理软件复杂性的方法。分而治之。

【讨论】:

    【解决方案3】:

    函数的要点是允许代码重用和更清晰的代码。如果您只执行一次真的很简单,那么该功能可能是不必要的。

    话虽如此,将代码拆分为函数外观并没有明显的错误。如果它使您的生活更轻松或您的代码更具可读性,那么请继续使用它们。

    【讨论】:

      【解决方案4】:

      看起来不错,至少在摘要中。

      将程序准确分解为函数取决于函数的作用,但如果最终结果由函数组成,每个函数执行一项由函数名称完整描述的任务,那么您就处于正确的轨道。

      如果您发现自己拥有大量具有逻辑分组的函数,您可以考虑将它们划分为模块。如果你有很多函数使用相同的数据,你可以考虑创建一个类来保存数据和相应的函数。

      【讨论】:

        【解决方案5】:

        你正在做一个权衡。通常,将代码模块化是一件好事。大多数人做得不够。它增加了代码的可重用性和(通常)可读性。但可能会走得太远:如果您发现自己对哪些函数调用哪些函数感到困惑,并且可读性开始下降,您可能需要重新考虑您的设计。

        需要注意的另一件事是调用函数需要大量开销,这可能很重要。每次调用函数时,都必须创建激活记录并将其放在call stack 上。对于简单得离谱的函数,这种开销是不值得的。例如,如果您正在实现一个需要 2 个数字的平均值的排序函数(也许选择快速排序的枢轴?),您最好只写 (a+b)/2 而不是定义一个函数

        def avg(a, b):
            return (a+b)/2
        

        您提出了一个非常好的问题,这绝对是您应该不断思考的问题,但显然很难给出具体的答案。随着您编写越来越多的代码,您会感觉更好。

        【讨论】:

        • 是的,不知道我为什么这样做...修复了。
        猜你喜欢
        • 1970-01-01
        • 2011-03-02
        • 1970-01-01
        • 2023-02-08
        • 2016-04-06
        • 2016-04-11
        • 2018-09-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多