中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python3 中作為一等對象的函數解析

發布時間:2020-10-20 15:22:45 來源:腳本之家 閱讀:137 作者:StarryLand 欄目:開發技術

Python3 函數

函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段。

函數能提高應用的模塊性,和代碼的重復利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。

在 Python 語言中,函數與整數、字符串、字典等基本數據類型一樣,都是 一等對象 。所謂一等對象,即滿足如下三個條件:

  • 在運行時創建
  • 能賦值給變量
  • 能作為函數的參數或返回值

以下 IDLE 中的代碼即在運行時創建了函數 factorial :

>>> def factorial(n):
...   '''calculates n!'''
...   return 1 if n < 2 else n * factorial(n-1)
...
>>> factorial(5)
120
>>> factorial.__doc__
'calculates n!'
>>> type(factorial)
<class 'function'>
>>> fact = factorial
>>> fact
<function factorial at 0x7f55bc771c10>
>>> fact(5)
120
>>> list(map(fact, range(10)))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]

從輸出中可以看出, factorial 是 function 類的實例對象, __doc__ 是 factorial 對象眾多屬性中的一個。

可以把 factorial 函數賦值給變量 fact ,通過 fact 變量調用 factorial 函數。還可以把 factorial 作為參數傳遞給 map 函數。

這些行為表現了函數作為一等對象的特性。

一、高階函數

接受函數作為參數,或者把函數作為返回值的函數即為 高階函數 。

如內置用于排序的 sorted 函數,它的 key 參數用于傳入一個函數,在需要排序的每個元素上執行特定的操作。如根據單詞長度對多個字符串進行排序:

>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=len)
['fig', 'apple', 'cherry', 'banana', 'raspberry', 'strawberry']

任何單參數的函數都可以作為 key 的值傳給 sorted 函數,如把單詞反向拼寫作為排序條件:

>>> def reverse(word):
...   return word[::-1]
...
>>> reverse('test')
'tset'
>>> sorted(fruits, key=reverse)
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

map、filter 與 reduce

函數式編程語言通常會提供 map 、 filter 和 reduce 三個高階函數或者實現了類似功能的函數。Python3 中的列表推導和生成器即具有 map 和 filter 函數的功能。

參考如下示例:

>>> def fact(n):
...   return 1 if n < 2 else n * fact(n-1)
...
>>> list(map(fact, range(6)))
[1, 1, 2, 6, 24, 120]
>>> [fact(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> list(map(fact, filter(lambda n: n % 2, range(6))))
[1, 6, 120]
>>> [fact(n) for n in range(6) if n % 2]
[1, 6, 120]

通過列表推導可以完成與 map 或 filter 函數類似的工作,且可讀性更高,也避免了使用 lambda 表達式。

reduce 在 Python2 中是內置函數,但在 Python3 中被移到了 functools 模塊中。 reduce 可以把某個操作連續地應用到某個序列上,累計所有的結果,把產生的一系列值規約成一個值。因此常用于求和計算,但內置的 sum 函數在可讀性和性能方面更優。

>>> from functools import reduce
>>> from operator import add
>>> reduce(add, range(101))
5050
>>> sum(range(101))
5050

二、匿名函數

可以使用 lambda 關鍵字在 Python 表達式內創建匿名函數。

在函數的參數列表中最適合使用匿名函數。如前面的根據字符串反序后的結果對單詞列表進行排序,可以使用 lambda 匿名函數替代傳入 sorted 的 reverse 函數:

>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=lambda word: word[::-1])
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']

lambda 表達式 lambda words: words[::-1] 即等同于之前的 reverse 函數:

def reverse(word):
   return word[::-1]

除了作為參數傳給某個高階函數外,Python 很少使用匿名函數。

三、可調用對象

除了用戶自定義的函數,其他可調用對象也可以使用調用運算符(即 () )。

Python 的數據模型中共包含 7 種可調用對象:

  • 用戶自定義函數:使用 def 語句或 lambda 表達式創建的函數
  • 內置函數:由 C 語言(CPython)實現的函數,如 len 或 time.strftime 等
  • 內置方法:使用 C 語言實現的方法,如 dict.get
  • 方法:在類的定義體中定義的函數
  • 類:類在調用時會使用 __new__ 方法創建實例,然后運行 __init__ 初始化實例,最后將實例返回給調用方。調用類相當于調用函數。
  • 類的實例:如果類的定義中實現了 __call__ 方法,則其實例可以作為函數調用
  • 生成器:使用 yield 關鍵字的函數或方法。可以返回生成器對象。

使用內置的 callable() 函數可以確認對象是否可調用。

任何 Python 對象都可以表現得像函數,只需實現該實例的 __call__ 方法。

如下面的 bingocall.py ,從列表中隨機取出一個元素:

import random
class BingoCage:
  def __init__(self, items):
    self._items = list(items)
    random.shuffle(self._items)
  def pick(self):
    try:
      return self._items.pop()
    except IndexError:
      raise LookupError('pick from empty BingoCage')
  def __call__(self):
    return self.pick()
bingo = BingoCage(range(50))
print(bingo.pick())
# => 38
print(bingo())
# => 22
print(callable(bingo))
# => True

bingo 是 BingoCage 類的一個實例,由于 BingoCage 類中實現了 __call__ 方法,則 bingo 對象是可調用的( bingo() )。

四、支持函數式編程的模塊

operator

在函數式編程中,經常需要將算術運算符當作函數使用。如不使用遞歸計算階乘。

使用 reduce 和 lambda 表達式計算階乘:

>>> from functools import reduce
>>> def fact(n):
...   return reduce(lambda a, b: a*b, range(1, n+1))
...
>>> fact(5)
120

Python 中的 operator 為多個運算符提供了對應的函數,可以避免寫 lambda a, b: a*b 這種匿名函數。

使用 reduce 和 operator.mul 計算階乘:

>>> from operator import mul
>>> from functools import reduce
>>> def fact(n):
...   return reduce(mul, range(1, n+1))
...
>>> fact(5)
120

operator 模塊中還有一類 itemgetter 和 attrgetter 函數,可以替代從序列中取出元素或讀取屬性的 lambda 表達式。

如根據元組中的第二個元素對多個元組進行排序:

>>> metro_data = [
...   ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
...   ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
...   ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
...   ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
...   ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
... ]
>>> from operator import itemgetter
>>> for city in sorted(metro_data, key=itemgetter(1)):
...   print(city)
...
('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833))
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889))
('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
('Mexico City', 'MX', 20.142, (19.433333, -99.133333))
('New York-Newark', 'US', 20.104, (40.808611, -74.020386))

如果把多個參數傳遞給 itemgetter ,則該函數會返回由提取的值構成的元組:

>>> cc_name = itemgetter(1, 0)
>>> for city in metro_data:
...   print(cc_name(city))
...
('JP', 'Tokyo')
('IN', 'Delhi NCR')
('MX', 'Mexico City')
('US', 'New York-Newark')
('BR', 'Sao Paulo')

attrgetter 與 itemgetter 作用類似,可以根據名稱提取對象的屬性。

operator 模塊中還有一個 methodcaller 函數,可以用來在某個對象上調用由參數指定的方法。

>>> from operator import methodcaller
>>> s = 'The time has come'
>>> upcase = methodcaller('upper')
>>> upcase(s)
'THE TIME HAS COME'
>>> hiphenate = methodcaller('replace', ' ', '-')
>>> hiphenate(s)
'The-time-has-come'
functools.partial

高階函數 functools.partial 用來 部分應用 某個函數。即基于某個函數創建一個新的可調用對象,并把原函數的某些參數固定。

如使用 partial 把一個接受雙參數的函數改編成單參數的可調用對象:

>>> from operator import mul
>>> from functools import partial
>>> triple = partial(mul, 3)
>>> triple(7)
21
>>> list(map(triple, range(1, 10)))
[3, 6, 9, 12, 15, 18, 21, 24, 27]

partial() 函數返回一個 functools.partial 對象,該對象提供對原函數的訪問和固定原函數參數的行為。

>>> def greeting(words, name):
...   return f'{words}, {name}!'
...
>>> from functools import partial
>>> greeting2 = partial(greeting, name='skitar')
>>> greeting2("what's up")
"what's up, skitar!"
>>> greeting2
functools.partial(<function greeting at 0x7f70f31788b0>, name='skitar')

總結

以上所述是小編給大家介紹的Python3 中作為一等對象的函數解析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

莱芜市| 鄂尔多斯市| 霞浦县| 嘉峪关市| 丹阳市| 嘉兴市| 昌邑市| 南雄市| 平度市| 维西| 永胜县| 扎赉特旗| 卓尼县| 灵宝市| 务川| 临沭县| 比如县| 宁波市| 武平县| 五峰| 紫云| 嘉禾县| 西华县| 安化县| 张家界市| 九龙坡区| 元朗区| 泾源县| 石渠县| 金昌市| 措勤县| 麻江县| 丹棱县| 仁化县| 扎兰屯市| 桦甸市| 根河市| 左权县| 哈巴河县| 新河县| 铜鼓县|