我读过一本Python教科书,其中包含以下与闭包结合使用的闭包功能。该排序功能应该首先对属于特殊group
集的数字进行优先级排序,然后对其余部分进行排序:
def sort_priority(values, group):
def helper(x):
if x in group:
return (0, x)
return (1, x)
values.sort(key=helper)
numbers = [8, 3, 1, 2, 5, 4, 7, 6]
group = {2, 3, 5, 7}
sort_priority(numbers, group)
print(numbers)
输出:
[2, 3, 5, 7, 1, 4, 6, 8]
x
中helper(x)
参数的实际值在哪里?答案 0 :(得分:1)
sort()中的key参数需要一个函数,并将该函数应用于要排序的每个列表元素。在您的示例中,值的每个元素都传递到helper()中,然后该助手将检查该元素是否在组中。然后,排序将比较元组列表,并且第一个元素为0的元组总是会出现在第一个元素为1的元组之前。
来源: https://wiki.python.org/moin/HowTo/Sorting#Key_Functions
答案 1 :(得分:1)
排序键是一种生成替代值以供您排序的函数。对替代值进行排序后强加的顺序将强加在原件上。排序键一次应用于列表的每个元素。因此,而不是按照
的命令排序[8, 3, 1, 2, 5, 4, 7, 6]
您正在按以下顺序排序
[helper(8), helper(3), helper(1), helper(2), helper(5), helper(4), helper(7), helper(6)]
对于列表中的每个元素, helper
都会被调用一次,就像您一样有效
[helper(x) for x in values]
现在您正在按以下命令排序
[(1, 8), (0, 3), (1, 1), (0, 2), (0, 5), (1, 4), (0, 7), (1, 6)]
通过将元素制成元组,您可以将集{2, 3, 5, 7}
的元素用零“标记”,该元素将始终排在用“ 1”标记的元素之前。这是因为首先比较每个元组的第一个元素“标签”。
对键进行排序时,实际值将以相同的顺序放置。
较新版本的Python根本不支持比较器,例如,与C和Java不同:根本没有必要。正确构造的键函数可以完成比较器的所有工作,并且每个元素仅需要评估一次,而无需评估多次。当然,密钥本身仍然需要比较相同的次数。
排序键还允许您对没有自然排序的元素列表进行排序(不支持<
之类的比较运算符)。使用右键,您甚至可以对包含通常无法相互比较的不同类型元素的列表进行排序。
另一方面,布尔值是Python中整数的特殊子类:False == 0
和True == 1
。由于这些标签是您用来将密钥分为几类的,因此您可以重写helper
来避免出现以下条件:
def helper(x):
return (x not in group, x)
附录
为帮助您更好地理解键排序,下面的实现与将键传递给sort
方法有效地实现了相同的作用,但不是就地实现(更像是sorted
在):
def my_sorted(iterable, key):
iterable = list(iterable)
elements = [(key, index) for index, key in enumerate(iterable)]
elements.sort()
return [iterable[index] for _, index in elements]
这将执行以下操作:
答案 2 :(得分:0)
摘要:
因为像这样的函数,有一个用于该项目的参数,顺便说一句,它等效于lambda x: ..
,也许您对此更加熟悉,所以您要通过该函数对值进行排序,基本上是直接helper
在某种意义上相当于lambda x: helper(x)
也许更熟悉,顺便说一句,它不是一个元组,而是一个集合,因为它包含花括号并且不包含冒号
因此,一个接一个地回答您的问题:
1)传递帮助器(x)中x参数的实际值在哪里?
该方法将该方法应用于每个函数,并且您从上面知道,它等效于
lambda x: helper(x)
。2)我知道Python在元组中首先比较0到0的索引,然后是1到1的索引,等等。但不太确定在这种情况下如何使用返回的元组进行比较。
好吧,因为您要在
helper
函数中返回值,所以它将按照这种方式进行排序。