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 ha开发者_JS百科ve 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!
__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.
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
It sorts list nums
in place using a key
function object DistanceFrom(10)
. It needs to be callable because key
needs to be callable. The resulting output is sorted by their "remoteness" from 10, that is 9 is the closest value to 10, 101 is the farthest one.
After the object is initialised and passed as a key
parameter to the sort
method, on each iteration it will be called with the current value (that's what x
is) and returned value would be used to determine x
's position in the resulting list.
When you call something that means you are expecting it to return a value. When you create a class that has the __call__
method defined, you are dictating that an instance of that class can behave as a function does.
For the purpose of this question, this:
class DistanceFrom(object):
def __init__(self, origin):
self.origin = origin
def __call__(self, x):
return abs(x - self.origin)
Is functionally equivalent to:
def distance_from(origin, other):
return abs(other - origin)
As for the key
argument to sort, here is your explanation straight from the Python documentation:
key specifies a function of one argument that is used to extract a comparison key from each list element:
key=str.lower
. The default value is None (compare the elements directly)
The Python docs are quite good whenever I find I don't understand the fundamentals. I located these with google.
The key
parameter is a function that sort will call on the elements of the list. I located this doc by googling sort site:http://docs.python.org/
and then searching for key=
.
__call__
is a function you can add to an object to make that object callable as if it were a function. I found this doc by googling __call__ site:http://docs.python.org/
and then following the link to the doc for __call__
.
精彩评论