python3对传递给sorted()的“key”参数的方法做了什么?

时间:2009-04-21 02:37:48

标签: python python-3.x sorted

我有一个关于python如何处理传递给sorted()的方法的问题。请考虑以下小脚本:

#!/usr/bin/env python3

import random

class SortClass:
    def __init__(self):
        self.x = random.choice(range(10))
        self.y = random.choice(range(10))
    def getX(self):
        return self.x
    def getY(self):
        return self.y

if __name__ == "__main__":
    sortList = [SortClass() for i in range(10)]
    sortedList = sorted(sortList, key = SortClass.getX)
    for object in sortedList:
        print("X:", object.getX(),"Y:",object.getY())

其中输出类似于以下内容:

X: 1 Y: 5
X: 1 Y: 6
X: 1 Y: 5
X: 2 Y: 8
X: 2 Y: 1
X: 3 Y: 6
X: 4 Y: 2
X: 5 Y: 4
X: 6 Y: 2
X: 8 Y: 0

此脚本根据每个实例的x字段的值对SortClass对象进行排序。但是请注意,排序的“key”参数指向SortClass.getX,而不是指向SortClass的任何特定实例。我对python如何实际使用传递为“key”的方法感到困惑。调用像这样的getX()是否有效,因为传递给它的对象与“self”参数的类型相同?这是“关键”论证的安全用法吗?

2 个答案:

答案 0 :(得分:8)

类的方法只是函数。

class MyClass(object):
...     def my_method(self): pass
...
>>> MyClass.my_method
<function my_method at 0x661c38>

当您从类的实例中获取方法时,Python使用一些魔法(称为描述符)来返回绑定方法。绑定方法会在调用实例时自动插入实例作为第一个参数。

>>> MyClass().my_method
<bound method MyClass.my_method of <__main__.myClass object at 0x6e2498>>

但是,正如您所注意到的,您也可以使用实例作为第一个参数直接调用该函数:MyClass.my_method(MyClass())

这就是sorted()发生的事情。 Python使用列表中的项调用函数SortedClass.getx,该项恰好是SortedClass的一个实例。

(顺便说一句,有更好的方法来做你正在做的事情。首先,不要使用方法来公开像getX这样的属性。使用属性或普通属性。另外,看看{{ 1}}和operator.itemgetter。)

答案 1 :(得分:0)

本杰明的答案+1。

另外,如果你想在Python中掌握排序,请阅读Sorting HowTo:http://docs.python.org/howto/sorting.html