【问题标题】:Readability in nested conditional statements嵌套条件语句的可读性
【发布时间】:2015-07-14 07:58:06
【问题描述】:

我目前正在用 Python 编写一个程序来为射影几何建模,而射影点的同余函数看起来很糟糕。

(对于任何感兴趣的人,如果两个投影点都位于通过原点的一条直线上,则它们是全等的。)

class Point(object):
    def __init__(self, a, b, c):
        self.coords = [ a, b, c ]

    def congruent(self, other):
        ratio = 0
        for i in range(3):
            if self.coords[i] != 0 and other.coords[i] != 0:
                if ratio is 0:
                    ratio = other.coords[i] / self.coords[i]
                elif ratio != other.coords[i] / self.coords[i]:
                    return False
            elif self.coords[i] != 0 or other.coords[i] != 0:
                return False
        return True

我是 Python 新手,但我知道通常有一种“Pythonic”的方式来做所有事情。考虑到这一点,我将如何使这更具可读性?

【问题讨论】:

  • 这个问题似乎是主观的、基于讨论和意见的......并没有真正的客观答案。
  • 代码检查 ratio 为 0 后,将 ratio 赋予一个新值。在那之后,永远不应该重新分配比率。不过,可能有更好的方法来做到这一点。
  • @Patrick,使用循环外的 0 坐标设置比率,然后在索引 1 处开始循环。这将更清楚地表明它在循环期间不会发生变化。
  • 我投票结束这个问题,因为它应该被迁移到codereview.stackexchange.com
  • @RobertH 结束问题对迁移没有任何帮助,如果您认为应该迁移,请单击“标记”->需要版主干预->说您认为应该迁移。跨度>

标签: python conditional-statements code-readability


【解决方案1】:

这个怎么样:

def congruent(self, other, eps=0.001):
    ratios = (c1 / c2 for c1, c2 in zip(self.coords, other.coords) if c1 or c2)
    try:
        first = next(ratios)
        return all(abs(ratio - first) < eps for ratio in ratios)
    except ZeroDivisionError:
        return False
  1. 如果可能,最好直接在元素上操作而不是在索引上操作(zip 很方便)。
  2. 对于either 坐标不为零的情况,列表推导获取所有坐标比率。如果两者都是,那很好,它会被排除在外。
  3. ZDE 仅在 c1 非零且 c2 为零时发生,因此这是失败的。
  4. 最后,如果所有比率都相等,我们通过。

注意:如果您不使用 Python 3,则应将 from __future__ import division 添加到文件顶部,以免整数坐标值得到不正确的结果。

编辑:为每个 @JoranBeasley 的浮动比率添加了短路和 epsilon-comparison。

【讨论】:

  • 呸,甚至比我的好。 ...我觉得您可以使用所有短路和发电机...但是很好的答案+1
  • @JoranBeasley 是的,我考虑将all 放入try,这是一个简单的替换,但它有点损害可读性。
  • 0.0/0.0 确实给了我一个 ZDE,所以不完全确定该位会按预期工作,但看起来足够可信
  • @JoranBeasley 添加了短路,检查一下:)。如果两者都是0.0,那么它们将被排除在比率列表之外,因为if c1 or c2False
  • Point(1,1,1).congruent(Point(0,0,0)) 返回 False
【解决方案2】:
def congurent(self,other):
    ratio = None
    for a,b in zip(self,other):
        if a != 0 and b != 0:
            if ratio is None: 
                 ratio = a/float(b)
            elif abs(ratio - a/float(b))>0.001:
                 return False
        elif a!=0 or b!=0:
            return False
     return True

可能更 Pythonic...虽然它真正改变的是你如何迭代列表(它的行数相同)

【讨论】:

  • 甜蜜。 abs(ratio - a/float(b))&gt;0.001 用于浮点比较吗?
  • 是的,很难用浮点数测试相等性,因为它们是:P
【解决方案3】:

也许使用if self.coords[i] 代替if self.coords[i] != 0(类似的例子也一样)和if not ratio 代替if ratio is 0。在 Python 中,任何非零值都会通过if 子句,所以你不需要检查它是否非零,它是自动的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 2012-02-17
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多