python中的闭包优先级排序功能

时间:2018-09-24 03:44:41

标签: python

我读过一本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]
  1. 要传递的xhelper(x)参数的实际值在哪里?
  2. 我了解Python在元组中首先比较0到0的索引,然后是1到1的索引,等等。但不太确定在这种情况下如何使用返回的元组进行比较。

3 个答案:

答案 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 == 0True == 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]

这将执行以下操作:

  1. 将输入转换为可以被索引的内容(序列),因为并非所有可迭代的变量都可以立即被索引。
  2. 计算每个元素的键以及原始列表中的索引。对键进行排序后,这将使您可以按正确的顺序提取元素。它还为分类提供了额外的稳定性。 Python的默认Timsort已经稳定了,但是键之间的任何关系都会被索引破坏。
  3. 按键对键和索引列表进行排序。
  4. 从原始序列中提取与每个已排序元素相对应的元素,然后返回结果。

答案 2 :(得分:0)

摘要:

因为像这样的函数,有一个用于该项目的参数,顺便说一句,它等效于lambda x: ..,也许您对此更加熟悉,所以您要通过该函数对值进行排序,基本上是直接helper在某种意义上相当于lambda x: helper(x)也许更熟悉,顺便说一句,它不是一个元组,而是一个集合,因为它包含花括号并且不包含冒号

因此,一个接一个地回答您的问题:

  

1)传递帮助器(x)中x参数的实际值在哪里?

     
    

该方法将该方法应用于每个函数,并且您从上面知道,它等效于lambda x: helper(x)

  
     

2)我知道Python在元组中首先比较0到0的索引,然后是1到1的索引,等等。但不太确定在这种情况下如何使用返回的元组进行比较。

     
    

好吧,因为您要在helper函数中返回值,所以它将按照这种方式进行排序。