Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding __call__ and list.sort(key)

Tags:

python

sorting

I have the following code I am trying to understand:

>>> class DistanceFrom(object):
        def __init__(self, origin):
            self.origin = origin
        def __call__(self, x):
            return abs(x - self.origin)  

>>> nums = [1, 37, 42, 101, 13, 9, -20]
>>> nums.sort(key=DistanceFrom(10))
>>> nums
[9, 13, 1, 37, -20, 42, 101]

Can anyone explain how this works? As far as I have understood, __call__ is what is called when object() is called - calling the object as a function.

What I don't understand is how nums.sort(key=DistanceFrom(10)). How does this work? Can anyone please explain this line?

Thanks!

like image 207
user225312 Avatar asked Oct 27 '10 14:10

user225312


2 Answers

__call__ in python allows a class to be run as if it's a function. You can try this out manually:

>>> dis = DistanceFrom(10)
>>> print dis(10), dis(5), dis(0)
0 5 10
>>> 

What sort does is call that function for every item in your list and uses the returned value as sort key. In this example you'll get a list back with the items closest to 10 first, and the one further away more towards the end.

like image 93
Mew Avatar answered Sep 30 '22 19:09

Mew


Here I have defined a function DistanceFrom() which can be used in a similar way to your class, but might be easier to follow

>>> def DistanceFrom(origin):
...     def f(x):
...         retval = abs(x - origin)
...         print "f(%s) = %s"%(x, retval)
...         return retval
...     return f
... 
>>> nums = [1, 37, 42, 101, 13, 9, -20]
>>> nums.sort(key=DistanceFrom(10))
f(1) = 9
f(37) = 27
f(42) = 32
f(101) = 91
f(13) = 3
f(9) = 1
f(-20) = 30
>>> nums
[9, 13, 1, 37, -20, 42, 101]

So you see that the object returned by DistanceFrom is called once for each item of nums and then nums is returned sorted in accordance with the returned values

like image 25
John La Rooy Avatar answered Sep 30 '22 21:09

John La Rooy