attrgetter:按对象属性排序时更改默认顺序

attrgetter: Altering Default Order When Sorting by Object Attribute

我正在使用 Python 3 的 operator 模块中的 attrgetter 函数来对对象列表(命中)进行排序。每个对象都有 12 个属性,我的排序函数可以输入其中的任何一个,以便以任何需要的方式对列表进行排序。我感兴趣的排序属性包含字符串。这是我的代码中的相关片段。

from operator import attrgetter
...
def sort_hits_by_attribute(hits, attribute, backwards = False):
    """Takes a lits of hits and sorts them by some attribute.
    """
    return sorted(hits, key = attrgetter(attribute), reverse = backwards)

这是一个 "hit" 对象及其属性的示例。

  name: ...
  entity_1: coffee cultivation
  entity_2: ...
  full_statement: ...
  category: ...
  rule: ...
  syn_configs: ...
  lex_conditions: ...
  sentence_number: ...
  close_call: False
  message: ...
  id: 119

如果我按属性 entity_1 对我的对象列表进行排序,则上述对象排序 一个 entity_1 字段以 an 开头的实例之后大写字母:例如 "Coffee" 甚至 "Zoo."

我想使用类似 casefold() 的函数,这样大写字母就会排在小写字母的旁边和后面。但是,casefold() 仅对字符串有效,因此使用 key = attrgetter(attribute).casefold() returns 一个 AttributeError.

如何保留 sort_hits_by_attribute() 的功能——即按函数调用期间传入的属性排序——但强制 Python 使用不同的顺序 {aAbBcCdDeE...}这样做?

我找到了答案 here,感谢@KylePDavis,他提供了一个通用的解决方案,可以将属性作为参数传入。密钥是使用 lambda 函数定义密钥。

我的代码现在看起来如下。请注意输入检查以验证 (1) 列表不为空以及 (2) 感兴趣的属性是否确实属于可以使用 casefold().[=15 排序的类型 (str) =]

def sort_hits_by_attribute(hits, attribute, backwards=False):
    """Takes a lits of hits and sorts them by some attribute.

    For instance, group duplicate relation hits together by sorting
    on full_statement.
    """

    if hits:
        if isinstance(attrgetter(attribute)(hits[0]), str):
            return sorted(hits, 
                key = lambda A: attrgetter(attribute)(A).casefold(), 
                reverse = backwards)
        else:
            return sorted(hits, 
                key = attrgetter(attribute), 
                reverse = backwards)

我没有将此问题标记为重复,因为引用的问题的最喜欢的答案并不是对这种情况特别重要的答案。