Eugene Wolf
Eugene Wolf

Reputation: 69

<lambda>() missing 2 required positional arguments: 'y' and 'z'

I've looked it over several times, but still can't understand what seems to be wrong here. This is the cosine similarity function written below, and also where its called with 2 vectors.

def cosine_sim(v1, v2):
     return (lambda x,y,z: x / sqrt(y * z))(reduce(lambda x,y: (x[0] + y[0] * y[1], x[1] + y[0]**2, x[2] + y[1]**2), izip(v1,v2),(0,0,0)))

cosine_sim(first_vector,second_vector)

Error:


TypeError Traceback (most recent call last) in () ----> 1 cosine_sim(firstvector,secondvector)

in cosine_sim(v1, v2) 1 def cosine_sim(v1, v2): ----> 2 return (lambda x,y,z: x / sqrt(y * z))(reduce(lambda x,y: (x[0] + y[0] * y[1], x[1] + y[0]**2, x[2] + y[1]**2), izip(v1,v2),(0,0,0)))

TypeError: () missing 2 required positional arguments: 'y' and 'z'

Upvotes: 1

Views: 5844

Answers (1)

ShadowRanger
ShadowRanger

Reputation: 155438

Your reduce call returns a three-tuple, so you're calling your lambda x, y, z with x as that three-tuple, and no arguments for y or z.

The simplest fix is to use the splat operator, *, to unpack the return from reduce so the three-tuple is converted to three sequential positional arguments:

def cosine_sim(v1, v2):
    return (lambda x,y,z: x / sqrt(y * z))(*reduce(lambda x,y: (x[0] + y[0] * y[1], x[1] + y[0]**2, x[2] + y[1]**2), izip(v1,v2),(0,0,0)))
    #                       change is here ^

Note that one-lining this is ugly as hell, and you're likely better off making it (at least) a two-liner, just to reduce complexity. Even keeping reduce, you could simplify a little to just:

def cosine_sim(v1, v2):
    x, y, z = reduce(lambda x,y: (x[0] + y[0] * y[1], x[1] + y[0]**2, x[2] + y[1]**2), izip(v1,v2),(0,0,0))
    return x / sqrt(y * z)

which is basically what your lambda was attempting, but with lower overhead (no need to call more functions for no reason).

Removing reduce entirely would make it slightly longer, but again, easier to interpret:

def cosine_sim(v1, v2):
    x = y = z = 0
    for a, b in izip(v1, v2):
        x += a * b
        y += a ** 2
        z += b ** 2
    return x / sqrt(y * z)

Give better names to the variables if possible, and this is pretty decent code (and likely faster to boot).

Upvotes: 3

Related Questions