避免使用全局变量,但要使代码易于理解

2024-06-16 10:41:49 发布

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

以下代码包括一些类和函数,用于生成可行的组合,作为解决下料优化问题的第一步。你知道吗

from collections import namedtuple, Counter
from itertools import combinations_with_replacement

roll_extra_width = 2
max_roll_count = 5
# and other parameters

class Roll(namedtuple('Roll', ['grade', 'thickness', 'width', 'length'])):
    def __repr__(self):
        return f'{self.grade}x{self.thickness}x{self.width:}x{self.length}'


class RollSet(Counter):
    def __repr__(self):
        return '\n' + '\n'.join(f'{key}: {qty}' for key, qty in self.items())

    def roll_count(self):
        return sum(self.values())

    def width(self):
        return sum(roll.width + roll_extra_width for roll in self.elements())


def get_viable_sets(rolls: list, min_width: int, max_width: int):
    roll_sets = (RollSet(combination) for combination in combinations_with_replacement(rolls, max_roll_count))
    viable_sets = [rset for rset in roll_sets if min_width < rset.width() < max_width]
    return viable_sets


def other_funcs(*args):
    # uses Roll and RollSet a lot
    pass


if __name__ == '__main__':
    rolls = [('N', 20, 300, 6000),
             ('N', 20, 350, 6000),
             ('N', 20, 400, 6000),
             ('N', 20, 500, 6000)]

    rolls = [Roll(*x) for x in rolls]

    min_width = 1000
    max_width = 2000

    viable = get_viable_sets(rolls, min_width, max_width)
    for rset in viable:
        print(rset)

    # More code using the defined classes

代码使用全局变量来保存一些参数值。
我知道这是一种非常糟糕的做法,可能会导致许多问题,但它具有以下可取的特性:
它将定义的类和函数的参数数量保持在最小,并使代码更易于阅读和理解。你知道吗

我尝试过使用容器类,但最终不得不将它的实例作为参数传递给其他每个函数/类,比如RollSet(rolls, param.roll_extra_width),而不仅仅是RollSet(rolls)。这似乎是不必要的冗余,因为初始化后参数将始终保持不变。你知道吗

有人能不能建议一种更好的方法来保存参数值,而不让代码被冗长的参数列表和重复的参数弄得乱七八糟?你知道吗


Tags: 代码inselfforreturndefsetswidth
2条回答

首先,我只想提一下,仅仅因为全局变量是坏的并不意味着没有地方放它们。你自己决定是否愿意接受不利的一面。你知道吗

容器类是一个很好的主意,通常我会使用它。在查看代码的特定情况下,我将初始化类RollSetRoll中的roll_extra_widthmax_roll_count。看看你的代码,这些是唯一使用变量的地方,这些类是被反复调用的,而不是实际的全局变量。你知道吗

下面是一个更清楚的例子:

class RollSet(Counter):
    def __init__(self):
        roll_extra_width = 2
        max_roll_count = 5

希望有帮助!你知道吗

我看不出有什么特别的问题

roll_extra_width = 2
max_roll_count = 5

它们本质上是代码中的常量,您在模块的顶部声明了它们,而不是在整个代码中散布它们,也就是Magic Numbers antipattern。顺便说一句,魔术字符串也是一种东西:if objecttype == "customer":

但是,如果它们是常量,您不妨将它们大写,这是在这些情况下通常的惯例。你知道吗

ROLL_EXTRA_WIDTH = 2
MAX_ROLL_COUNT = 5

另外,全局变量的一个重要部分是关于可变变量的共享全局状态。这些是不可变的整数,所以这里不用担心。你知道吗

如果你有很多这样的常数,你可能想把它们分流成一个常数.py或诸如此类,否则会使您的代码变得混乱。这是一个偏好的问题,其他人可能会有其他更好的建议。你知道吗

相关问题 更多 >