Python传播者会说Python没有switch语句的原因是因为它有字典。那么......我怎么能用字典来解决这个问题呢? 问题是所有值都在评估中,并根据输入提出异常。
这只是一个存储数字或数字列表并提供乘法的类的一个愚蠢的例子。
class MyClass(object):
def __init__(self, value):
self._value = value
def __mul__(self, other):
return {
(False, False): self._value * other._value ,
(False, True ): [self._value * o for o in other._value] ,
(True , False): [v * other._value for v in self._value] ,
(True , True ): [v * o for v, o in zip(self._value, other._value)],
}[(isinstance(self._value, (tuple, list)), isinstance(other._value, (tuple, list)))]
def __str__(self):
return repr(self._value)
__repr__ = __str__
>>> x = MyClass(2.0)
>>> y = MyClass([3.0, 4.0, 5.0])
>>> print x
2.0
>>> print y
[3.0, 4.0, 5.0]
>>> print x * y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __mul__
TypeError: can't multiply sequence by non-int of type 'float'
我可以解决的一种方法是在每个值前加上“lambda:”,然后在字典查找后调用lambda函数....“}(isinsta ...)”
有更好的方法吗?
答案 0 :(得分:4)
是的,为这些不同的选项定义小型lambda:
def __mul__(self, other):
scalar_times_scalar = lambda x,y: x*y
scalar_times_seq = lambda x,y: [x*y_i for y_i in y]
seq_times_scalar = lambda x,y: scalar_times_seq(y,x)
seq_times_seq = lambda x,y: [x_i*y_i for x_i,y_i in zip(x,y)]
self_is_seq, other_is_seq = (isinstance(ob._value,(tuple, list))
for ob in (self, other))
fn = {
(False, False): scalar_times_scalar,
(False, True ): scalar_times_seq,
(True , False): seq_times_scalar,
(True , True ): seq_times_seq,
}[(self_is_seq, other_is_seq)]
return fn(self._value, other._value)
理想情况下,您当然只能在类或模块范围内定义这些lambdas一次。为了便于参考,我在这里用__mul__
方法展示了它们。
答案 1 :(得分:1)
我可以想到两种方法:
一些if
语句。对于True
和False
的四种组合,它并没有那么糟糕。从我看到的if
... elif
... elif
...子句的序列在Python代码中并不少见。
创建一次dict(作为类字段,而不是实例字段),并在其中存储(lambda)函数。这比以前的方法更好地扩展,并且对于许多选项来说更快(尽管我不知道“很多”的价值)。
答案 2 :(得分:1)
我认为这里的要点是可读性 您展示的字典查找肯定难以阅读,因此需要维护。
在我看来,编写软件时的主要目标应该是可读性;出于这个原因,我会去一组if / elif明确地比较这两个值(而不是对类型的映射);然后,如果测量显示性能问题,可以探索其他解决方案(如使用函数进行字典查找)。