在这种情况下,我应该使用什么来代替全局变量?Python3.8

2024-06-02 07:29:06 发布

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

我有一个相当大的项目,由于共谋和隐私,我只想张贴我的问题的意义

def H():
   B()
   ...
   # return with something else

def G():
   ...
   B()
   # return with something else

def F():
   dosomething(counter, ...)
   ...

def E():
   ...

def D():
   ...
   B()
   ...
   # return with something else

def C():
   ...

def B():
    ...
    if success:
        global counter += 1 
    ...
    

def A():
    B()
    C()
    D() # the list goes on...
    ...
    

def main():
    try:
        A()
    except Exception as e:
        ...
    else:
        ...

counter = 0


if __name__ == '__main__':
    main()

正如您所看到的,问题在于,每次调用B()的函数获得成功结果时,都会有一个全局变量递增

我做了关于stackoverflow的研究,大多数人都在诅咒全局变量,这些变量不只是用作contant,它们是邪恶的,应该不惜一切代价避免它们

大多数人并没有真正解释原因和主要原因,但一些人解释说,由于复杂性、可读性和混乱性的增加,应该避免使用全局变量,我完全理解并观察是否使用不当

作为一种解决方案,大多数人说它将使用返回,特别是一个元组(返回两个值)

然而在我的例子中,这个项目相当大,我列出了使用全局变量和收益的利弊

在我的例子中使用全局变量的优点

  • 全局变量只由一个函数递增,其他函数调用该函数,因此不存在复杂性或混乱
  • 花费我2行代码

在我的例子中使用全局变量的缺点

  • ?

在我的例子中,使用收益而不是全局变量的优点

  • ?

在我的例子中,使用返回而不是全局变量的缺点

  • 我必须重写基本上所有内容,因为我必须将计数器传递给main,然后传递给D(),H(),B(),G(),A()。我必须重写函数变量,以便它们使用正确的返回元素,我必须重写参数,我必须重写参数,我必须编辑类。真是一团糟

所以在我的例子中,我绝对不同意使用返回值而不是全局变量

使用全局变量->;字面上有两行代码,简单易懂,直观易懂

使用退货->;可能需要重写50-100行,并花费时间修复类和对象,增加了混乱和复杂性

有什么我看不到的吗?你有什么想法吗


Tags: 项目函数returnifmaindefwithcounter
2条回答

如果我理解您的问题,那么您可能需要使用closure

由于B函数有条件地递增计数器,并且计数器在其他地方使用,因此可能需要类似于工厂函数的东西,它返回两个函数的元组,一个执行B,另一个返回当前值counter

大概是这样的:

def factory():
    counter = 0

    def B():
        ...
        if success:
            counter += 1
        ...

    def get_counter():
        return counter

    return (B, get_counter)


B, get_counter = factory()

// execute B
B()

// get the value of counter
current_counter = get_counter()

简单使用全局计数器的问题,尤其是在大型项目中,很容易变得不清楚变量会发生什么。 使用return可以简化调试和跟踪,因为您可以单独获取return语句并查看它们,也可以简化重用,因为您可以获取return语句(或其值)并重用它,甚至在需要/需要时重新分配它

现在,因为我们不知道你的函数到底做什么,除了基本结构之外,对代码的了解也很少,所以很难给出明确的建议

另一种选择是将变量放入类中,因为对象也是全局可调用的,但更加健壮。 例如:

class B:
    def __init__(self):
        self.counter = 0
    def increment_counter(self):
        self.counter +=1
    def get_counter(self):
        return self.counter

然后创建一个对象并在其他函数中调用objects函数

最后,对于一些一般性建议,不要害怕重写代码,即使它可能需要很多努力,如果它提供了代码质量的实质性改进的话。在这个过程中,你可以学到很多东西,这可能会帮助你避免将来的错误

相关问题 更多 >