<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          這幾個Python內(nèi)置的高階函數(shù),真香

          共 6803字,需瀏覽 14分鐘

           ·

          2020-07-28 17:47

          閱讀本文大概需要 6 分鐘。

          奇怪,reduce去哪了?

          什么是高階函數(shù)?,一句話,就是可以接受其他函數(shù)名稱作為自己參數(shù)的函數(shù)。函數(shù)式編程說的就是這個。Python中一切皆對象,函數(shù)也是一個對象,可以作為變量名稱傳遞給其他函數(shù)調(diào)用,高階函數(shù)就是一種特殊的函數(shù),有 5 個內(nèi)置的函數(shù)可以大大提高我們的編程效率,分別是 sorted、filter、zip、map、reduce,這里除了 zip 函數(shù),其他都是高階函數(shù)。它們的用武之地非常廣泛,要不也不會作為內(nèi)置函數(shù)了。今天分享下它們的用法,掌握之后,你一定會覺得,真香!

          1、sorted 函數(shù)

          函數(shù)原型:sorted(iterable, *, key=None, reverse=False)
          首先,它是一個穩(wěn)定的排序算法,接收一個可迭代對象,兩個必須通過關(guān)鍵字傳參的可選參數(shù),返回一個排序后的可迭代對象。key 是用來指定按照那個信息進行比較排序的函數(shù),比如 key = str.lower,如果不指定,則默認按照可迭代對象中的元素進行比較。
          基本用法:
          >>>?v_list?=?[5,2,3,4,1]
          >>>?sorted(v_list)
          [1,?2,?3,?4,?5]
          >>>?v_tuple?=?(5,2,3,4,1)
          >>>?sorted(v_tuple)
          [1,?2,?3,?4,?5]
          >>>?v_dict?=?{5:'a',2:'b',3:'c',4:'d',1:'e'}
          >>>?sorted(v_dict)
          [1,?2,?3,?4,?5]
          >>>
          可以看出,只要是可迭代對象,都可以使用 sorted。
          進階用法,指定關(guān)鍵字進行排序:
          >>>?v_dict?=?{5:'a',2:'b',3:'c',4:'d',1:'e'}
          >>>?sorted(v_dict,key=lambda?x:v_dict[x])
          [5,?2,?3,?4,?1]
          >>>?student_tuples?=?[
          ...?????('john',?'A',?15),
          ...?????('jane',?'B',?12),
          ...?????('dave',?'B',?10),
          ...?]
          >>>?sorted(student_tuples,?key=lambda?student:?student[2])???#?sort?by?age
          [('dave',?'B',?10),?('jane',?'B',?12),?('john',?'A',?15)]
          還可以對對象進行排序,代碼如下:
          class?Student:
          ????def?__init__(self,?name,?grade,?age):
          ????????self.name?=?name
          ????????self.grade?=?grade
          ????????self.age?=?age
          ????def?__repr__(self):
          ????????return?repr((self.name,?self.grade,?self.age))

          student_objects?=?[
          ????Student('john',?'A',?15),
          ????Student('jane',?'B',?12),
          ????Student('dave',?'B',?10),
          ]
          sorted(student_objects,?key=lambda?student:?student.age)???#?sort?by?age

          #[('dave',?'B',?10),?('jane',?'B',?12),?('john',?'A',?15)]
          上述指定 key 的用法非常普遍,python 還提供了非常便利的訪問器 operator, operator 模塊有 itemgetter() 、 attrgetter() 和 methodcaller() 函數(shù)。用法也簡單易學(xué),如下:
          itemgetter 指定按待排序元素指定位置的數(shù)據(jù)進行排序:
          >>>?student_tuples
          [('john',?'A',?15),?('jane',?'B',?12),?('dave',?'B',?10)]
          >>>?from?operator?import?itemgetter,?attrgetter
          >>>?sorted(student_tuples,?key=itemgetter(2))
          [('dave',?'B',?10),?('jane',?'B',?12),?('john',?'A',?15)]
          如果要排序的是類,可以使用 attrgetter 指定按那個屬性排序:
          >>>?class?Student:
          ...?????def?__init__(self,?name,?grade,?age):
          ...?????????self.name?=?name
          ...?????????self.grade?=?grade
          ...?????????self.age?=?age
          ...?????def?__repr__(self):
          ...?????????return?repr((self.name,?self.grade,?self.age))
          ...
          >>>?student_objects?=?[
          ...?????Student('john',?'A',?15),
          ...?????Student('jane',?'B',?12),
          ...?????Student('dave',?'B',?10),
          ...?]
          >>>?student_objects
          [('john',?'A',?15),?('jane',?'B',?12),?('dave',?'B',?10)]
          >>>?sorted(student_objects,?key=attrgetter('age'))
          [('dave',?'B',?10),?('jane',?'B',?12),?('john',?'A',?15)]
          >>>
          還可以指定多個關(guān)鍵字排序,比如先按照 grade 排序,再按照 age 排序:
          >>>?sorted(student_tuples,?key=itemgetter(1,2))
          [('john',?'A',?15),?('dave',?'B',?10),?('jane',?'B',?12)]
          >>>?sorted(student_objects,?key=attrgetter('grade',?'age'))
          [('john',?'A',?15),?('dave',?'B',?10),?('jane',?'B',?12)]
          排序默認使用升序,如果要降序,傳入一個關(guān)鍵字參數(shù) reverse = True 即可。
          >>>?sorted(student_tuples,?key=itemgetter(2),?reverse=True)
          [('john',?'A',?15),?('jane',?'B',?12),?('dave',?'B',?10)]
          排序是穩(wěn)定的:
          >>>?data?=?[('red',?1),?('blue',?1),?('red',?2),?('blue',?2)]
          >>>?sorted(data,?key=itemgetter(0))
          [('blue',?1),?('blue',?2),?('red',?1),?('red',?2)]
          排序算法使用 Timsort,Timsort 是一種混合穩(wěn)定的排序算法,源自歸并排序和插入排序,旨在較好地處理真實世界中各種各樣的數(shù)據(jù),從 2.3 版本起,Timsort 一直是 Python 的標(biāo)準(zhǔn)排序算法。它還被 Java SE7, Android platform, GNU Octave,?谷歌瀏覽器和 Swift 用于對非原始類型的數(shù)組排序。

          2、filter 函數(shù)

          函數(shù)原型:filter(function, iterable)
          filter() 函數(shù)用于過濾一個可迭代對象,過濾掉不符合條件的元素,返回由符合條件元素組成的新的可迭代對象。
          filter 接收兩個參數(shù),第一個為函數(shù),第二個為可迭代對象,可迭代對象中的每個元素作為參數(shù)傳遞給函數(shù)進行判斷,然后返回 True 或 False,最后將返回 True 的元素放到新可迭代對象中。
          如獲取列表中的偶數(shù):
          >>>?v_list?=?[1,2,3,4,5,6]
          >>>?new?=?filter(lambda?x:?x%2?==0,?v_list)
          >>>?list(new)
          [2,?4,?6]
          >>>?number_list?=?range(-5,?5)
          >>>?less_than_zero?=?list(filter(lambda?x:?x?0,?number_list))
          >>>?less_than_zero
          [-5,?-4,?-3,?-2,?-1]
          filter 使用方法很簡單,也很好理解,不多說。

          3、zip 函數(shù)

          函數(shù)原型:zip(*iterables)
          提到 zip 你一定會想到壓縮,不過這里表示的是一種重新組合的意思,看下面的代碼就知道了:
          >>>?list(zip("abc","xy"))
          [('a',?'x'),?('b',?'y')]
          >>>?list(zip("abc","xy",[1,2,3,4]))
          [('a',?'x',?1),?('b',?'y',?2)]
          函數(shù)接受不限數(shù)目的可迭代對象,按照個數(shù)最小的可迭代對象進行重新組合,組合的策略就是按照原有的順序進行,第 i 個元組包含來自每個參數(shù)序列或可迭代對象的第 i 個元素。當(dāng)所輸入可迭代對象中最短的一個被耗盡時,迭代器將停止迭代。當(dāng)只有一個可迭代對象參數(shù)時,它將返回一個單元組的迭代器。不帶參數(shù)時,它將返回一個空迭代器。用代碼來解釋 zip 就是:
          def?zip(*iterables):
          ????#?zip('ABCD',?'xy')?-->?Ax?By
          ????sentinel?=?object()
          ????iterators?=?[iter(it)?for?it?in?iterables]
          ????while?iterators:
          ????????result?=?[]
          ????????for?it?in?iterators:
          ????????????elem?=?next(it,?sentinel)
          ????????????if?elem?is?sentinel:
          ????????????????return
          ????????????result.append(elem)
          ????????yield?tuple(result)
          還有一種理解就是行轉(zhuǎn)列,比如:
          >>>?x?=?[1,?2,?3]
          >>>?y?=?[4,?5,?6]
          >>>?zipped?=?zip(x,?y)
          >>>?list(zipped)
          [(1,?4),?(2,?5),?(3,?6)]
          如果是二維數(shù),使用 zip 行轉(zhuǎn)列就太方便了:
          >>>?array?=?[?[1,2,3,4],[5,6,7,8],[9,10,11,12]]
          >>>?list(zip(*array))
          [(1,?5,?9),?(2,?6,?10),?(3,?7,?11),?(4,?8,?12)]
          注意,zip 以最短的可迭代對象來進行組合,其他元素丟棄,整個過程并不報錯,如果不希望丟棄元素,可以使用 itertools 中的 zip_longest 方法,如下:
          >>>?x?=?[1,2,3]
          >>>?y?=?[4,5]
          >>>?z?=?[6,7,8,9]
          >>>?list(zip(x,y,z))
          [(1,?4,?6),?(2,?5,?7)]
          >>>?from?itertools?import?zip_longest
          >>>?list(zip_longest(x,y,z))
          [(1,?4,?6),?(2,?5,?7),?(3,?None,?8),?(None,?None,?9)]

          4、map/reduce 函數(shù)

          函數(shù)原型:
          • map(function, iterable, …)

          • reduce(function, iterable[, initializer])

          如果你讀過 Google 的那篇大名鼎鼎的論文 “MapReduce: Simplified Data Processing on Large Clusters”,你就能大概明白 map/reduce 的概念。
          簡單來說,map 就是分發(fā)任務(wù),reduce 就是對結(jié)果進行匯總。Python 內(nèi)置的高階函數(shù) map/reduce 也是這個理兒。
          比如,要對列表中的每個元素執(zhí)行特定的任務(wù),如果列表元素個數(shù)是 10 個,就要調(diào)用 10 次,有了 map 一行代碼搞定:
          >>>?def?fun(x):
          ...?????return?x*x
          ...
          >>>?v_list?=?[1,2,3,4,5,6,7,8,9,10]
          >>>?map(fun,v_list)
          0x10ff240f0>
          >>>?list(map(fun,v_list))
          [1,?4,?9,?16,?25,?36,?49,?64,?81,?100]
          map() 傳入的第一個參數(shù)是 fun,即函數(shù)對象本身。由于 map object 是一個 Iterator,Iterator 是惰性序列,因此通過 list() 函數(shù)讓它把整個序列都計算出來并返回一個 list。有人說我不用 map,寫個循環(huán)也可以搞定,沒錯,但那樣可讀性就變差了,下面的代碼,你能一眼看出來 把 fun(x) 作用在 list 的每一個元素并把結(jié)果生成一個新的 list:
          L?=?[]
          for?n?in?[1,?2,?3,?4,?5,?6,?7,?8,?9,10]:
          ????L.append(fun(n))
          print(L)
          再看 reduce 的用法。reduce 把一個函數(shù)作用在一個可迭代對象[x1, x2, x3, …]上,第一個對象的結(jié)果作為參數(shù)傳遞給下一次調(diào)用,因此這個函數(shù)必須接收兩個參數(shù)。
          初學(xué)者可以簡單的理解為累加、累積、就是前一步的結(jié)果是下一步的輸入,舉個例子:
          >>>?from?functool?import?reduce
          >>>?def?add(x,y):
          ...?????return?x+y
          ...
          >>>?reduce(add,[1,3,5,7])
          16
          Python3 中 reduce 被移到了 functools,因為 Guido 先生討厭 reduce。
          當(dāng)然求和運算可以直接用 Python 內(nèi)建函數(shù) sum(),沒必要動用 reduce。但是如果要把序列 [1, 3, 5, 7, 9] 變換成整數(shù) 13579,reduce 就可以派上用場:
          >>>?from?functools?import?reduce
          >>>?def?fn(x,?y):
          ...?????return?x?*?10?+?y
          ...
          >>>?reduce(fn,?[1,?3,?5,?7,?9])
          13579
          這個例子本身沒多大用處,但是,如果考慮到字符串 str 也是一個序列,對上面的例子稍加改動,配合map(),我們就可以寫出把 str 轉(zhuǎn)換為 int 的函數(shù):
          from?functools?import?reduce

          DIGITS?=?{'0':?0,?'1':?1,?'2':?2,?'3':?3,?'4':?4,?'5':?5,?'6':?6,?'7':?7,?'8':?8,?'9':?9}

          def?char2num(s):
          ????return?DIGITS[s]

          def?str2int(s):
          ????return?reduce(lambda?x,?y:?x?*?10?+?y,?map(char2num,?s))
          也就是說,即使 Python 不提供 int() 函數(shù),完全可以自己寫一個把字符串轉(zhuǎn)化為整數(shù)的函數(shù),而且只需要幾行代碼!
          (完)
          參考文檔:
          • Python 官方文檔:https://docs.python.org/zh-tw/3/library/functions.html

          • map/reduce:https://www.liaoxuefeng.com/wiki/1016959663602400/1017329367486080

          • Timsort:https://zh.wikipedia.org/wiki/Timsort

          推薦閱讀:
          python 基礎(chǔ)系列--可迭代對象、迭代器與生成器
          深入理解迭代器和生成器
          瀏覽 39
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品婷婷在线 | 亚洲第一色五月 | 无码国产精品96久久久久孕妇 | 亚洲乱码精品 | 男操女逼射逼心国产中字传媒视频 |