使用"状态变量"在生成器表达式

时间:2016-11-01 14:56:03

标签: python generator

在我的应用程序中,我基本上需要使用列表"中所有先前术语的总和,但是列表不仅仅是一个列表而是一个tupples生成器(其中第三个索引)是#34;冒犯"一个。

作为一个例子(非工作代码显然但它应该表明这个想法):

def calculate_minimal_charge_rate(self) -> float:
    o = self.orbit
    shadow_time = o.generate_shadow_light_time_list()
    P = self.getIdlePowerConsumption()
    a = 0
    return max(a += ind[1]; P * ind[2].period / \
            (ind[2].period - a) for ind in shadow_time)

或者是一个最小的工作示例(请注意,这很愚蠢,因为来自itertools的另一个函数可以为我解决这个问题)

def calculate_minimal_charge_rate(self) -> float:
    o = self.orbit
    shadow_time = o.generate_shadow_light_time_list()
    P = self.getIdlePowerConsumption()
    a = 0
    return max(a += ind[1]; a for ind in shadow_time)

现在显而易见的解决方案"是使用for循环:

def calculate_minimal_charge_rate(self) -> float:
    o = self.orbit
    shadow_time = o.generate_shadow_light_time_list()
    P = self.getIdlePowerConsumption()
    a = 0
    max_power = 0
    for ind in shadow_time:
        a += ind[1] 
        preq = P * ind[2].period / \
                (ind[2].period - a)
        if preq > max_power:
            max_power = preq
    return max_power

但对于这样一个简单的事情来说,这并不是那么啰嗦"?哦,为了完整起见,这里是orbit.generate_shadow_light_time_list()

def generate_shadow_light_time_list(self):
    """
    Returns total max time in shadow
    Iterativelly calls max_time_in_shadow for each orbit until star is found
    """
    o = self
    try:
        while o.parent.brightness <= 0:
            t = o.max_time_in_shadow()
            yield (o.period - t, t, o)
            o = o.parent.orbit
    except AttributeError:
        return
    return

1 个答案:

答案 0 :(得分:2)

由于您试图在生成器表达式中累积状态,因此您需要一个单独的对象来为您维护它。您的当前for循环解决方案可能是维护和可读性方面最简单的方法。另一个选择是编写自己的生成器,它将维护您需要的状态并将其传递给max。感谢@ patrick-haugh建议这个解决方案:

def calculate_minimal_charge_rate(self) -> float:
    def get_that_quantity():
        a = 0
        for item in shadow_time:
            a += item[1]
            p = item[2].period
            yield power * p / (p - a)

    power = self.getIdlePowerConsumption()
    shadow_time = self.orbit.generate_shadow_light_time_list()
    return max(get_that_quantity())

希望看到这段代码会让你相信没有充分的理由使用它。唯一的好处是,您基本上是通过生成器将大部分for循环传递给max,而不是自己实现max的逻辑。你的案件足够专业,你可能不会因为混淆这样的事情而获得任何额外的里程。

<强>更新

我通过将参数移动到使用它的函数中来消除了将参数传递给生成器的需要。这可以说实现与for循环相同,因为它没有引入任何新代码,但确实删除了max逻辑。