Python代码/函数布局

Python代码/函数布局,python,Python,我正在学习Python,并试图找出构造代码的最佳方法 假设我有一个长函数,想把它分解成更小的函数。在C中,我会在顶层将其设置为“静态”函数(因为这是函数的唯一级别)。我也可能会向前声明它,并将它放在使用它的现在缩短的函数之后 现在来看Python。在Python中,我可以选择创建嵌套函数。由于这个新的“内部”函数实际上只是为了可读性目的而分离出来的较大函数的一部分,并且仅由它使用,因此听起来它应该是一个嵌套函数,但将此函数放在父函数中会导致整个函数仍然很长,因为实际上没有从中移出任何代码!尤其是

我正在学习Python,并试图找出构造代码的最佳方法

假设我有一个长函数,想把它分解成更小的函数。在
C
中,我会在顶层将其设置为“静态”函数(因为这是函数的唯一级别)。我也可能会向前声明它,并将它放在使用它的现在缩短的函数之后

现在来看Python。在Python中,我可以选择创建嵌套函数。由于这个新的“内部”函数实际上只是为了可读性目的而分离出来的较大函数的一部分,并且仅由它使用,因此听起来它应该是一个嵌套函数,但将此函数放在父函数中会导致整个函数仍然很长,因为实际上没有从中移出任何代码!尤其是由于函数在调用之前必须完全编码,这意味着实际的短函数在这个伪长函数的末尾一直处于低位,这使得可读性非常糟糕


在这种情况下,什么是良好的实践?

据我所知,Python中内部函数的主要优点是它们继承了封闭函数的作用域。因此,如果您需要访问主函数作用域中的变量(例如参数或局部变量),可以使用内部函数。否则,做任何你喜欢和/或觉得最可读的事情

编辑:
也请参见。

最好的做法是保持低调。这实际上意味着将长函数分解为许多较小的函数

复杂度通过if,while,do,for,?的数量来衡量:, 中的catch、switch、case语句和运算符&&和| |(加一) 构造函数、方法、静态初始值设定项或实例的主体 初始化器。它是对可能路径的最小数量的度量 通过来源,从而获得所需测试的数量。 一般认为1-4是好的,5-7好,8-10考虑重构, 11+现在重新计算

我建议采纳来自Sonar的建议,Sonar是一种代码质量分析工具。重构此类代码的一个好方法是使用TDD。首先编写单元测试以覆盖当前函数的所有执行路径。之后,您可以放心地重构,单元测试将保证您不会破坏任何东西


另一方面,如果您的长函数很长,但在其他方面已经具有较低的圈复杂度,那么我认为该函数是否嵌套无关紧要。

将较小的函数放在自己的文件中,然后将其导入主函数如何?你会有类似于:

def main_func():
    from impl import a, b, c

    a()
    b()
    c()
我认为这种方法具有很高的可读性:您可以看到较小的函数从何而来,以防您想要查看它们,导入它们只是一行程序,主函数的实现是直接可见的。通过选择适当的文件名/位置,您还可以告诉用户这些函数不适用于
main_func
之外的使用(您在Python中没有隐藏的真实信息)


顺便说一下:这个问题没有一个正确答案。

所以我能理解的是,你有一个长函数,比如:

def long_func(blah, foo, *args):
    ...
...
my_val = long_func(foo, blah, a, b, c)
你所做的是:

def long_func(blah, foo, *args):
    def short_func1():
        ...
    def short_func2():
        ...
    ...
    short_func1()
    short_func2()
    ...
...
my_val = long_func(foo, blah, a, b, c)
你还有很多选择,我将列出两个:

  • 把它编成一个班

    class SomeName(object):
        def __init__(self, blah, foo, *args):
            self.blah = blah
            self.foo = foo
            self.args = args
            self.result = None  # Might keep this for returning values or see (2)
    
        def short_func1(self):
            ...
        def short_func2(self):
            ...
        def run(self):  # name it as you like!
            self.short_func1()
            self.short_func2()
            return self.result  # (2) or return the last call, on you
    ...
    my_val = SomeName(foo, blah, a, b, c).run()
    
  • 制作另一个模块并将
    short_funcs
    放入其中。就像flyx建议的那样

    def long_func(foo, blah, *args):
        from my_module import short_func1, short_func2
    
        short_func1(foo)
        short_func2(blah)
    

  • 您想保持功能性还是在OOP中考虑编程?我认为最好将Python编程视为一组命名空间和范围。使用类、模块和包作为将某些类型的功能和行为(方法)绑定(封装)到某些给定类型(类)的实例的方法。嵌套应该谨慎使用,并且仅用于范围界定或避免名称空间冲突。您提出了一些有趣的观点,但问题不在于何时重构或如何断言质量。问题只是问在特定情况下如何构造或布局代码。@flornquake你是对的。我看了看症状的背后,建议治疗这个问题。告诉他是否嵌套这个功能将是一个止痛药,相反,我给了他治疗。有时候,虽然不总是这样,但你可以做得比逐字逐句地回答问题要好得多。他所描述的长期功能是一个正在制作中的恐怖故事,一个定时炸弹。他越早采取行动,对他就越好。是否嵌套函数的问题将在这个过程中消失。在我看来,OP已经知道何时重构以及如何拆分函数。他们想知道的是,当他们重构时,将得到的较小的函数放在哪里。