【问题标题】:Python lazy dictionary evaluationPython惰性字典评估
【发布时间】:2010-08-12 18:58:55
【问题描述】:

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 ...)”

有没有更好的办法?

【问题讨论】:

  • 采用任何类型的值的方法从OOP的角度来看是最糟糕的事情,这就是代码看起来如此丑陋的原因。

标签: python dictionary switch-statement lazy-evaluation


【解决方案1】:

是的,为这些不同的选项定义小的 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)

当然,理想情况下,您只需要在类或模块范围内定义一次这些 lambda。为了便于参考,我刚刚在__mul__ 方法中展示了它们。

【讨论】:

    【解决方案2】:

    我可以在这里想到两种方法:

    • 一些if 语句。对于TrueFalse 的四种组合,还不错。 if ... elif ... elif ... 的序列,据我所知,在 Python 代码中并不少见。

    • 创建一次字典(作为类字段,而不是实例字段),并在其中存储 (lambda) 函数。这比以前的方法扩展得更好,并且对于许多选项来说更快(尽管我不知道“many”的值)。

    【讨论】:

      【解决方案3】:

      我认为这里的重点是可读性。
      您展示的字典查找绝对难以阅读,因此难以维护。

      在我看来,编写软件的主要目标应该是可读性;出于这个原因,我会使用一组 if/elif 来明确比较这两个值(而不是拥有类型的映射);然后,如果测量显示性能问题,则可以探索其他解决方案(例如使用函数的字典查找)。

      【讨论】:

        猜你喜欢
        • 2018-04-01
        • 2014-02-08
        • 2013-03-11
        • 2017-01-18
        • 2018-11-11
        • 1970-01-01
        • 2015-05-29
        • 1970-01-01
        相关资源
        最近更新 更多