Pythonic方式做`如果x在y中x.attr == val`?

时间:2015-09-16 14:23:01

标签: python

我有一个类,它将多项式表示为一个术语集合,其中每个术语都有一个系数和一个指数。我正在研究课程的__add__方法,我想知道最有效的方法是什么:

def __add__(self, other):
    new_terms = []
    for term in self.terms:
        if there is a term in other with an exponent == term.exponent
            new_terms.append(Term(term.coef + other_term.coef, term.exponent))

令我感到震惊的是,我正在寻找以下内容:

if x in y where x.attr == val

或者在我的具体案例中:

if x in other where x.exponent == term.exponent

这样的事情存在吗?

2 个答案:

答案 0 :(得分:2)

在进行包含检查之前,您需要过滤列表。正如tobias_k建议的那样,您可以构建一个新列表,例如

[x for x in other if x.exponent == term.exponent]

这直接在if语句中起作用,因为空列表为False

if [x for x in other if x.exponent == term.exponent]:

但这会带来一些浪费的工作,因为它a)必须构建一个新的列表,并且b)一旦找到结果就不会短路。更好的方法是在生成器表达式中使用相同的语法:

(True for x in other if x.exponent == term.exponent)

然后您可以在if语句中使用它,但不会浪费任何工作:

if next((True for x in other if x.exponent == term.exponent), False):

答案 1 :(得分:0)

我认为你想要[x for x in y if x.attr == val],或者使用next使用相同的表达式来表示第一个这样的值。

在您的情况下,它可能看起来像这样:

def __add__(self, other):
    for term in self.terms:
        for other_term in (x for x in other.terms 
                             if x.exponent == term.exponent):
            term.coefficient += other_term.coefficient

然而,这不会太好用。首先,__add__不应修改selfother,而应创建新的多项式。此外,这将忽略other中与self中的任何术语具有不同指数的任何值。第三,性能非常糟糕,因为它为other中的每个术语循环self中的术语列表,使其具有二次复杂性。

相反,我建议使用字典,将术语中的指数映射到它们的系数。事实上,你可能只需使用collections.Counter;它已经以正确的方式实现了__add__。像这样:

class Poly:

    def __init__(self, counts):
        self.terms = collections.Counter(counts)

    def __add__(self, other):
        return Poly(self.terms + other.terms)

    def __str__(self):
        return " + ".join("%dx^%d" % (c, x) for x, c in self.terms.items())

示例:

>>> Poly({2: 1, 1: 3, 0: 5}) + Poly({3: 1, 1: 2, 0: 3})
8x^0 + 5x^1 + 1x^2 + 1x^3