一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - Python函數(shù)式編程實例詳解

Python函數(shù)式編程實例詳解

2020-04-19 10:55theVicTory Python

這篇文章主要介紹了Python函數(shù)式編程,結(jié)合實例形式詳細(xì)分析了Python函數(shù)式編程高階函數(shù)、匿名函數(shù)、閉包及函數(shù)裝飾器等相關(guān)概念、原理與使用技巧,需要的朋友可以參考下

本文實例講述了Python函數(shù)式編程。分享給大家供大家參考,具體如下:

函數(shù)式編程就是一種抽象程度很高的編程范式,從計算機(jī)硬件->匯編語言->C語言->Python抽象程度越高、越貼近于計算,但執(zhí)行效率也越低。純粹的函數(shù)式編程語言編寫的函數(shù)沒有變量,因此,任意一個函數(shù),只要輸入是確定的,輸出就是確定的,這種純函數(shù)我們稱之為沒有副作用。而允許使用變量的程序設(shè)計語言,由于函數(shù)內(nèi)部的變量狀態(tài)不確定,同樣的輸入,可能得到不同的輸出,因此,這種函數(shù)是有副作用的。函數(shù)式編程的一個特點就是,允許把函數(shù)本身作為參數(shù)傳入另一個函數(shù),還允許返回一個函數(shù)!

Python對函數(shù)式編程提供部分支持,支持高階函數(shù)(函數(shù)可以作為變量傳入),支持閉包(返回一個函數(shù)),有限地支持匿名函數(shù)。由于Python允許使用變量,因此,Python不是純函數(shù)式編程語言。

1、高階函數(shù)

 

即可以通過變量名指向函數(shù),函數(shù)通過變量名作為參數(shù)傳給另一個函數(shù),并通過變量名來使用。例如下面將開方函數(shù)math.sqrt作為參數(shù)傳遞給變量f,變量名f就指向了函數(shù)math.sqrt,再通過變量f使用該函數(shù)給x、y開方。

?
1
2
3
4
5
import math
def add(x, y, f):
  return f(x) + f(y) # 函數(shù)作為參數(shù)傳遞給f來調(diào)用
res = add(25, 9, math.sqrt)
print(res)

map函數(shù)接收一個函數(shù) f 和一個 list,并把函數(shù) f 依次作用在 list 的每個元素上,得到一個iterators并返回。

?
1
2
3
4
def format_name(s):
  return s[0].upper()+s[1:].lower()  #將列表的每個元素首字母大寫,其他小寫
print(list(map(format_name, ['adam', 'LISA', 'barT'])))
#輸出:['Adam', 'Lisa', 'Bart']

filter()根據(jù)判斷函數(shù)f的結(jié)果自動過濾掉不符合條件的元素,以iterators返回剩下的元素

?
1
2
3
4
def is_odd(x):
  return x % 2 == 1 # 過濾函數(shù),x為奇返回True
f_res = filter(is_odd, [1, 4, 6, 7, 9, 12, 17])
print(list(f_res))  # 輸出過濾后的結(jié)果list:1 7 9 17

sorted()函數(shù)用于對可迭代的對象進(jìn)行排序,參數(shù)key=指定排序的關(guān)鍵字,這里可以借助functools.cmp_to_keys()將比較方法映射為自定義的方法。例如實現(xiàn)了降序排列,比較函數(shù)cmp返回值 -1 代表a 應(yīng)該排在 b 的前面,如果a排在b 的后面返回 1。如果 a、b相等返回 0。

?
1
2
3
4
5
6
7
8
9
import functools
def cmp(a, b):
  if b < a:
    return -1
  if a < b:
    return 1
  return 0
a = [1, 2, 5, 4]
print(sorted(a, key=functools.cmp_to_key(cmp)))

2、匿名函數(shù)和閉包

 

有時函數(shù)簡單到只有一個表達(dá)式時,為了簡化代碼可以使用匿名函數(shù)來代替,匿名函數(shù)一般形式為lambda 參數(shù):返回表達(dá)式,例如lambda x:x*x,就是傳入x參數(shù)并返回x的平方。例如在使用map()函數(shù)時需要傳入一個函數(shù)用于list的元素,此時可以使用匿名函數(shù)作為參數(shù)

?
1
2
3
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
res = map(lambda x: x * x, lst)  # 將匿名函數(shù)作用于lst
print(list(res))

函數(shù)的閉包(Closure)是指內(nèi)層函數(shù)引用了外層函數(shù)的變量,然后將內(nèi)層函數(shù)像變量一樣返回的情況。例如函數(shù)calc_prod()接收一個list,在其內(nèi)部定義一個函數(shù)multiply,計算list元素的乘積并將multiply返回。用f接收calc_prod()的返回函數(shù),并在之后調(diào)用該函數(shù)

?
1
2
3
4
5
6
7
8
9
def calc_prod(lst):
  def multiply():
    res=1
    for i in lst:
      res=res*i
    return res
  return multiply  # 將函數(shù)返回
f = calc_prod([1, 2, 3, 4])  # 接收返回函數(shù)
print(f())  # 調(diào)用返回函數(shù)

注意在函數(shù)閉包時要確保引用的局部變量在函數(shù)返回后不能變。例如下面的例子,當(dāng)count()函數(shù)返回3個函數(shù)時,由于f1、f2、f3并沒有被調(diào)用,所以并未計算 i*i。當(dāng) f1 被調(diào)用時,這3個函數(shù)所引用的變量 i 的值已經(jīng)變成了3,所以此時使用的變量i的值已經(jīng)發(fā)生了改變,三個函數(shù)的輸出都是9。

?
1
2
3
4
5
6
7
8
9
10
def count():
  fs = []
  for i in range(1, 4):
    def f():
      print(i)  # 函數(shù)f1()調(diào)用時i已經(jīng)變?yōu)?
      return i*i
    fs.append(f)
  return fs
f1, f2, f3 = count()
print(f1())      # 輸出9而不是1

3、函數(shù)裝飾器

 

函數(shù)裝飾器是指在原有函數(shù)的基礎(chǔ)上對函數(shù)作修改和裝飾操作。其基本思想是,既然函數(shù)可以像變量一樣作為參數(shù)傳入并且返回,那么我們可以將原來的函數(shù)傳入裝飾器函數(shù),然后增加我們需要的操作,之后在將原函數(shù)返回出來。

例如下面定義了一個裝飾器log用于打印函數(shù)名稱,原函數(shù)作為參數(shù)f傳入。在裝飾器中定義新的函數(shù)fn,其中參數(shù)列*args和**kw代表自適應(yīng)參數(shù)個數(shù),防止不同參數(shù)個數(shù)的函數(shù)在使用裝飾器時不匹配。在新函數(shù)fn中輸出原函數(shù)的名稱,之后將原函數(shù)原封不動地調(diào)用一遍并返回出去。最后返回新函數(shù)。

在使用裝飾器時,只需要在函數(shù)的定義前加一行@裝飾器名

?
1
2
3
4
5
6
7
8
9
def log(f): # 定義裝飾器log
  def fn(*args, **kw): # 定義新函數(shù)
    print('函數(shù)名: ' + f.__name__)  # 打印函數(shù)名
    return f(*args, **kw) # 在新函數(shù)中調(diào)用原函數(shù)并返回結(jié)果
  return fn # 返回新函數(shù)
@log # 為函數(shù)add添加裝飾器
def add(x, y):
  return x + y
print(add(1, 2))

如果希望給裝飾器傳入一個參數(shù),則需要定義三重嵌套的函數(shù),在最外層增加一層函數(shù)用于接收參數(shù)。例如希望在打印函數(shù)名之前輸出傳入的參數(shù)“DEBUG”

?
1
2
3
4
5
6
7
8
9
10
11
def log(prefix):
  def log_decorator(f):
    def wrapper(*args, **kw):
      print '[%s] %s()...' % (prefix, f.__name__)
      return f(*args, **kw)
    return wrapper
  return log_decorator
@log('DEBUG'# 為裝飾器傳入?yún)?shù)
def test():
  pass
test()

由于裝飾器實際上是創(chuàng)建了新的函數(shù)fn并替代了原函數(shù),所以原函數(shù)的相關(guān)信息例如函數(shù)名會被覆蓋,可以用@functools.wraps(f)來復(fù)制原函數(shù)的信息以保留下來。

?
1
2
3
4
5
6
7
import functools
def log(f):
  @functools.wraps(f)
  def fn(*args, **kw):
    print 'call...'
    return f(*args, **kw)
  return fn

偏函數(shù)可以為函數(shù)填上一個固定的參數(shù)值,從而生成一個新的函數(shù)。例如原函數(shù)add需要兩個參數(shù)x、y,通過指定y=1得到偏函數(shù)add1,這個函數(shù)只需要輸入一個參數(shù)x,從而計算x+1的值。

?
1
2
3
4
5
import functools
def add(x, y):
  return x + y
add1 = functools.partial(add, y=1)
print(add2(3))  # 輸出結(jié)果為4

希望本文所述對大家Python程序設(shè)計有所幫助。

原文鏈接:https://blog.csdn.net/theVicTory/article/details/95070465

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 免费稚嫩福利 | 国产在线观看a | 亚洲免费福利视频 | 精品九九视频 | 色狠狠色狠狠综合天天 | 国产精品亚洲片在线不卡 | 亚洲h片 | 日韩欧美推理片免费看完整版 | 久久99re2在线视频精品 | 国产精品亚洲精品观看不卡 | 4hc44四虎永久地址链接 | 国产精品毛片va一区二区三区 | 欧美一区二区三区免费不卡 | 韩国最新三级网站在线播放 | 精品久久一 | 日韩性事 | 国产小嫩模好紧 | 成人性色生活片免费网 | 忘忧草高清 | 吃瓜视频在线观看 | 久久se精品一区二区国产 | 175m美女被网友灌醉啪啪玩脚 | 国产精品久久久久jk制服 | 欧美午夜性春猛交bbb | 国外欧美一区另类中文字幕 | 日本高清在线观看天码888 | 国产成人精品一区二区 | 99在线观看视频免费精品9 | 公交车上插入 | 日韩免费在线看 | 成人午夜毛片 | 亚洲精品一 | www.9p234.com| 大妹子最新视频在线观看 | 国产尤物精品视频 | 538亚洲欧美国产日韩在线精品 | 国产女乱淫真高清免费视频 | ffyybb免费福利视频 | 国产福利资源网在线观看 | 我把寡妇日出水好爽 | 精品国产自在现线久久 |