我有一个类,它将多项式表示为一个术语集合,其中每个术语都有一个系数和一个指数。我正在研究课程的__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
这样的事情存在吗?
答案 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__
不应修改self
和other
,而应创建新的多项式。此外,这将忽略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