理解__call__和list.sort(键)

时间:2010-10-27 14:39:30

标签: python sorting

我想要了解以下代码:

>>> 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]

任何人都可以解释这是如何工作的吗?据我所知,__call__是调用object()时调用的函数 - 将对象作为函数调用。

我不明白的是nums.sort(key=DistanceFrom(10))。这是如何运作的?有人可以解释一下这行吗?

谢谢!

5 个答案:

答案 0 :(得分:8)

python中的

__call__允许一个类运行,就像它是一个函数一样。您可以手动尝试:

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

对列表中的每个项目调用该函数是什么类型,并使用返回的值作为排序键。在这个示例中,您将获得一个列表,其中第一个项目最接近10,而更远的一个项目更靠近末尾。

答案 1 :(得分:7)

在这里,我定义了一个函数DistanceFrom(),它可以以与您的类相似的方式使用,但可能更容易理解

>>> 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]

因此,对于每个DistanceFrom项,您会看到nums返回的对象被称为一次,然后nums将根据返回的内容返回{{1}}值

答案 2 :(得分:4)

使用nums函数对象key对列表DistanceFrom(10)进行排序。它需要是可调用的,因为key需要可调用。结果输出按其“远程”从10开始排序,即9是最接近10的值,101是最远的值。

初始化对象并将其作为key参数传递给sort方法后,在每次迭代时,将使用当前值(即x是)调用它并返回value将用于确定x在结果列表中的位置。

答案 3 :(得分:1)

当你打电话的时候意味着你希望它返回一个值。当您创建一个定义了__call__方法的类时,您要求该类的实例可以像函数一样运行。

出于这个问题的目的,这个:

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

在功能上等同于:

def distance_from(origin, other):
    return abs(other - origin)

至于要排序的key参数,这里直接来自Python文档:

  

key 指定一个函数   用于提取的参数   每个列表元素的比较键:   key=str.lower。默认值为   无(直接比较元素)

答案 4 :(得分:1)

每当我发现我不理解基础知识时,Python文档都非常好。我在谷歌找到了这些。

The key parameter是一个排序将调用列表元素的函数。我通过Google搜索sort site:http://docs.python.org/找到此文档,然后搜索key=

__call__是一个可以添加到对象的函数,使该对象可以调用,就好像它是一个函数一样。我通过Google搜索__call__ site:http://docs.python.org/找到了此文档,然后点击__call__文档的链接。