Reading in nested conditional statements

I am currently writing a Python program for modeling projective geometry, and the congruence function for the projective point looks rather unpleasant.

(for anyone interested, two projective points are congruent if they both lie on the same straight line through the origin.)

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

      

I'm new to Python, but I know there is generally a "Pythonic" way to do everything. With that in mind, how would I make it more readable?

+3


source to share


3 answers


How about this:

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

      

  • Prefers to work directly on elements rather than indexes if possible ( zip

    convenient).
  • The comprehension of the list gets all the matching coefficients for the cases where any coordinate is nonzero. If both of them are okay and he is excluded.
  • ZDE only occurs if c1

    nonzero but c2

    zero, so it crashes.
  • At the end we will go through if all relationships are equal.


Note. If you are not using Python 3, you must add from __future__ import division

to the beginning of the file to avoid getting incorrect results for integer coordinate values.

Edit: Added short-circuiting and epsilon comparison for float coefficients for @JoranBeasley.

+3


source


Maybe use if self.coords[i]

instead if self.coords[i] != 0

(same for similar examples) and if not ratio

instead if ratio is 0

. In Python, any non-zero value conveys a sentence if

, so you don't need to check if it's non-zero, it's automatic.



+1


source


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

      

maybe a little more pythonic ... although it really does change as you iterate over the list (its the same number of lines)

+1


source







All Articles