passing arguments to a function - do I need type ?

Steven D'Aprano steve at REMOVETHIScyber.com.au
Sun Jul 10 17:33:39 CEST 2005


On Sun, 10 Jul 2005 11:19:31 +0100, Philipp H. Mohr wrote:

> Hello,
> I got a newbie question, I have written the following distance function:

Great. Now, how about you tell us what you expect it to do? I assume
it calculates the Euclidean distance between two points. (If you
don't know what Euclidean distance is, don't worry about it -- it is
basically just the "normal" distance.)

Should it calculate the distance between points on a line? 2-D points on
a plane? 3-D points in space? Higher dimensions?

I'm going to assume you want your function to operate on any number of
dimensions.

> def distance(self,element1, element2):

You don't need "self" unless it is a method of a class.

>         dist = 0
>         for n in range(len(element1)):
>             dist = dist + pow((element1[n] - element2[n]),2)
>         print 'dist' + dist

Why are you printing the SQUARE of the distance?

>         return sqrt(dist)

Okay, here is a simpler method, complete with comments:

def distance(point1, point2):
    """Return the distance between two points in N-dimensional space.

    Example: if the points are (a,b) and (c,d) respectively, returns the
    Euclidean distance d = sqrt( (c-a)**2 + (d-b)**2 )

    Both points should have the same number of coordinates, each of which
    is a float or int. Points can be given as lists or tuples.
    """
    sum_sq = 0  # sum of squares of the differences
    if len(point1) != len(point2):
        # check for errors here because they might not be picked 
        # up later if we don't
        raise ValueError("Points have different number of dimensions")
    for i in range(len(point1)):
        x, y = point1[i], point2[i]  # extract the next two ordinates
        sum_sq = sum_sq + (y-x)**2  # and add the square of the difference
    return sum_sq**0.5

If you really care about accuracy, you should use the sqrt function from
the math module rather than **0.5.

Here is another version, using zip.

def distance(point1, point2):
    if len(point1) != len(point2):
        raise ValueError("Points have different number of dimensions")
    L = zip(point1, point2)
    sum_sq = 0
    for x,y in L:
        sum_sq = sum_sq + (y-x)**2
    return sum_sq**0.5

And finally, a one-liner using list comprehensions and no error-checking.

def distance(point1, point2):
    return sum([(y-x)**2 for x,y in zip(point1, point2)])**0.5



> and in order to be able to use len() and index element1[] the function
> needs to know that the arguments element1 and element2 are both listst
> or doesn't it ?

No. Lots of things can be passed to len() and indexed.

> I get the following error msg:
> 
> Traceback (most recent call last):
>   File "Memory.py", line 105, in ?
>     start.inputVector(inP2)
>   File "Memory.py", line 97, in inputVector
>     allDimensions[0].newAttribute(vector)
>   File "Memory.py", line 56, in newAttribute
>     dist = self.distance(n.getCenter,newElement)
>   File "Memory.py", line 75, in distance
>     for n in range(len(element1)):
> TypeError: len() of unsized object

And what is element1 when you get that error message? That's the first
thing I would look at. 

> AND if I take len out I get:
> 
> 
> Traceback (most recent call last):
>   File "Memory.py", line 105, in ?
>     start.inputVector(inP2)
>   File "Memory.py", line 97, in inputVector
>     allDimensions[0].newAttribute(vector)
>   File "Memory.py", line 56, in newAttribute
>     dist = self.distance(n.getCenter,newElement)
>   File "Memory.py", line 76, in distance
>     dist = dist + pow((element1[n] - element2[n]),2)
> TypeError: unsubscriptable object

Firstly, you seem to have a lot of modules there. What happens when you
call distance directly? Can you get it to work then?

Secondly, what are the values for element1 and element2?


-- 
Steven.




More information about the Python-list mailing list