3 Replies - 134 Views - Last Post: 09 July 2019 - 05:31 AM Rate Topic: -----

#1 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 560
  • View blog
  • Posts: 1,778
  • Joined: 27-December 13

Which code snippet is most pythonic?

Posted 08 July 2019 - 01:45 PM

As a spin-off from the Carambole challenge, I worked with a small function to find the intersection of two vectors, v1 and v2 originating from the points p1 and p2.

The function uses numpy for solving the algebra equations and I want the function to accept both standard tuples/lists and numpy's array type.

I came up with two solutions:

Number 1:
p1 = (1, 2)
v1 = (1, 2)

p2 = (5, 5)
v2 = (1, 3)

def intersection_1(p1, v1, p2, v2):
    """
    Calculates and returns the intersection between two
    vectors, v1 and v2, starting from points p1 and p2.

    Arguments must be numpy arrays.

    Returns the intersection as type 'numpy.ndarray'.
    """

    const = p2 - p1
    coeff = ((v1[0], -v2[0]), (v1[1], -v2[1]))
    n1, n2 = np.linalg.solve(coeff, const)
    return p1 + n1 * v1


print(intersection_1(*list(map(np.array,(p1, v1, p2, v2)))))


This function is short and (relatively) straightforward. The function requires the arguments to be numpy arrays.
This is ensured by a quite 'bumpy' function call.

I didn't like this clumsy function call so I made version 2 including a test for argument type:
p1 = (1, 2)
v1 = (1, 2)

p2 = (5, 5)
v2 = (1, 3)

def intersection_2(*args):
    """
    Calculates and returns the intersection between two
    vectors, v1 and v2, starting from points p1 and p2

    Arguments must be in the order: p1, v1, p2, v2

    Returns the intersection as type 'numpy.ndarray'
    """
    
    if any(not isinstance(arg, (np.ndarray)) for arg in args):
        return intersection_2(*list(map(np.array, args)))

    p1, v1, p2, v2 = args        
    const = p2 - p1
    coeff = ((v1[0], -v2[0]), (v1[1], -v2[1]))
    n1, n2 = np.linalg.solve(coeff, const)
    return p1 + n1 * v1


print(intersection_2(p1, v1, p2, v2))


Now, the function call is nice and tidy; I've moved all the 'mechanics' handling tuple/list input inside the function - but the function itself is less appealing.

My question: Which is most pythonic? Or do you have an even better suggestion?


In case you wonder about the math:
We need to solve this equation: p1 + n1 * v1 = p2 + n2 * v2; the unknown are n1 and n2. Rearranging to n1 * v1 - n2 * v2 = p2 - p1 which is formatted to fit directly into numpy's linalg.solve() method.

Maybe someone can find a better way to write the coeff; admittedly, ((v1[0], -v2[0]), (v1[1], -v2[1])) is bulky but I didn't find anything better.

Is This A Good Question/Topic? 1
  • +

Replies To: Which code snippet is most pythonic?

#2 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 560
  • View blog
  • Posts: 1,778
  • Joined: 27-December 13

Re: Which code snippet is most pythonic?

Posted 08 July 2019 - 02:42 PM

Oh, I can do this: coeff = np.transpose((v1, -v2)) in line 18 resp. 22.
So, disregard my last sentence in post #1.
Was This Post Helpful? 0
  • +
  • -

#3 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 560
  • View blog
  • Posts: 1,778
  • Joined: 27-December 13

Re: Which code snippet is most pythonic?

Posted 09 July 2019 - 03:58 AM

I've finally settled on this version:
p1 = (1, 2)
v1 = (1, 2)

p2 = (5, 5)
v2 = (1, 3)

def intersection_3(*args):
    """
    Calculates and returns the intersection between two
    vectors, v1 and v2, starting from points p1 and p2.

    Arguments must be in the order: p1, v1, p2, v2.
    Arguments can be tuples, lists and/or numpy arrays.

    Returns the intersection as type 'numpy.ndarray'.
    """
    
    p1, v1, p2, v2 = list(map(np.array, args))
    const = p2 - p1
    coeff = np.transpose((v1, -v2))
    n1, _ = np.linalg.solve(coeff, const)
    return p1 + n1 * v1


print(intersection_3(p1, v1, p2, v2))



It's surprising how difficult it can be to find a simple and clear solution....
Was This Post Helpful? 0
  • +
  • -

#4 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7494
  • View blog
  • Posts: 15,529
  • Joined: 16-October 07

Re: Which code snippet is most pythonic?

Posted 09 July 2019 - 05:31 AM

I prefer dissecting the bits, rather than subscripts. I find this easier to read and it has the bonus of playing better with some objects. A disadvantage is it being less compact, but I'd rather have clarity than brevity.

e.g.
def point_add(p1, p2):
    (x1, y1), (x2, y2) = pt1, pt2
    return (x1 + x2), (y1 + y2)
# vs.
def point_add(p1, p2):
    return (p1[0] + p2[0]), (p1[1] + p2[1])


Was This Post Helpful? 1
  • +
  • -

Page 1 of 1