官术网_书友最值得收藏!

3.7 排序不支持原生比較的對象

在Python中,并非所有的對象都支持原生的比較操作。但在實際應用中,我們需要對不支持原生比較的對象執行排序操作。

Python內置的sorted()函數有一個關鍵字參數key,其可以傳入一個callable對象。callable對象對每個傳入的對象返回一個值,這個返回值是sorted()函數排序傳入的對象后得到的。

如果應用程序中有一個User實例序列,我們希望通過它們的user_id屬性進行排序,這時可以提供一個以User實例為輸入并輸出對應user_id值的callable對象,示例如下:


class User(object):
    def __init__(self, user_id):
        self.user_id = user_id

    def __repr__(self):
        return 'User({})'.format(self.user_id)

if __name__ == "__main__":
    users = [User(23), User(3), User(99)]
    print(users)
    print(sorted(users, key=lambda u: u.user_id))

對于該示例,我們也可以通過operator.attrgetter()函數代替lambda()函數,示例如下:


from operator import attrgetter
    print(sorted(users, key=attrgetter('user_id')))

選擇使用lambda()函數還是attrgetter()函數取決于個人喜好。不過,attrgetter()函數通常會運行得快點,并且同時允許多個字段進行比較。這與operator.itemgetter()函數作用于字典類型很類似。

如果User實例還有一個first_name和last_name屬性,那么可以像下面這樣排序:


by_name = sorted(users, key=attrgetter('last_name', 'first_name'))

這里用到的技術同樣適用于像min()和max()之類的函數,示例如下:


print(min(users, key=attrgetter('user_id')))
print(max(users, key=attrgetter('user_id')))

擴展:按需選擇sort()或者sorted()函數。

各種排序算法以及它們的時間復雜度分析是很多企業面試人員經常會問的問題,這是因為在實際應用中確實會遇到各種需要排序的情況。Python中常用的排序函數有sort()和sorted()。這兩個函數并不完全相同,各有各的使用方式。兩者形式如下:

1)相比于sort()函數,sorted()函數使用范圍更為廣泛。這兩個函數有3個共同參數,即cmp、key和reverse。cmp為用戶定義的比較函數,其參數為兩個可比較的元素,可根據第一個參數與第二個參數的關系依次返回-1、0或1,默認參數為None;key是一個函數形式的參數,用來為每個元素提取比較值,默認值為None;reverse標識排序結果是否反轉。

2)當排序對象為列表的時候,兩者適用的場景不同。sorted()函數會返回一個排序后的列表,原有列表保持不變;sort()函數會直接修改原有列表,返回為None。若應用中需要保留原有列表,sorted()函數較為實用,否則選擇sort()函數。對于sort()函數,由于其不需要復制原有列表,所以消耗內存較少,效率也較高。

3)不論是sort()函數還是sorted()函數,傳入參數key比傳入參數cmp效率要高。cmp傳入的函數在整個排序過程中會調用多次,函數開銷較大;而key針對每個元素僅做一次處理,因此使用key比使用cmp效率要高。

主站蜘蛛池模板: 龙里县| 兰溪市| 太仆寺旗| 洛川县| 阳新县| 咸宁市| 南雄市| 桐庐县| 横山县| 娄烦县| 临江市| 新邵县| 内黄县| 宁德市| 盖州市| 胶南市| 东山县| 集贤县| 武夷山市| 平和县| 清河县| 海淀区| 都匀市| 独山县| 绥中县| 兴文县| 尖扎县| 喀喇| 阳信县| 怀化市| 临城县| 元朗区| 阳城县| 黑山县| 上饶市| 湄潭县| 保山市| 泾源县| 涡阳县| 仙游县| 赣州市|