【Python】编程笔记5
文章目錄
- 函數式編程(Functional Programming)
- 一、高階函數(Higher-order function)
- 二、map/reduce
- 1、map() 函數
- 2、reduce() 函數
- 三、filter
- 1、用 filter 求素數
- 四、sorted
- 1、數字
- 2、字符串
- 五、返回函數
- 1、函數作為返回值
- 2、閉包
- 3、匿名函數
- 4、裝飾器
- 5、偏函數
- 模塊
- 1、使用模塊
- 2、作用域
- 3、第三方庫
函數式編程(Functional Programming)
函數式編程:思想更接近于數學計算,抽象程度很高的編程范式,純粹的函數式編程語言編寫的函數沒有變量。
特點:允許把函數本身作為參數傳入另一個函數,還允許返回一個函數。
Python 允許使用變量,因此,Python 不是純函數式編程語言。
一、高階函數(Higher-order function)
函數本身也可以賦值給變量,即:變量可以指向函數。例如:函數名。
f = abs print(f(-10))輸出結果
10高階函數:一個函數就可以接收另一個函數作為參數。(既然變量可以指向函數,函數的參數能接收變量)
def add(x, y, f):return f(x) + f(y)print(add(-5, 6, abs))輸出結果
11二、map/reduce
Python 中內建了 map() 和 reduce() 函數。
1、map() 函數
map()函數:接收兩個參數,一個是函數,一個是 Iterable。map 將傳入的函數依次作用到序列的每個元素,并把結果作為新的 Iterator 返回。
def f(x):return x * x r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) print(list(r))## 把這個 list 所有數字轉為字符串 print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))輸出結果
[1, 4, 9, 16, 25, 36, 49, 64, 81] ['1', '2', '3', '4', '5', '6', '7', '8', '9']2、reduce() 函數
reduce()函數:把一個函數作用在一個序列 [x1, x2, x3, ...] 上,這個函數必須接收兩個參數, reduce 把結果繼續和序列的下一個元素做累積計算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)把序列[1, 3, 5, 7, 9]變換成整數 13579 的 reduce 實現:
from functools import reduce def fn(x, y):return x * 10 + y print(reduce(fn, [1, 3, 5, 7, 9]))輸出結果
13579str 類型 ==》int 類型
from functools import reduce def str2int(s):def fn(x, y):return x * 10 + ydef char2num(s):return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]return reduce(fn,map(char2num,s))# 13579 print(str2int('13579'))利用 lambda 函數進一步簡化:
def char2num(s):return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] def str2int(s):return reduce(lambda x,y:10 * x + y, map(char2num, s))str ==》float
def str2float(s):def char2num(s):return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]def fnMuti(x, y):return 10 * x + ydef fnDivid(x, y):return x / 10 + ydotIndex = s.index('.')return reduce(fnMuti, map(char2num, s[:dotIndex])) + reduce(fnDivid, list(map(char2num, s[dotIndex + 1:]))[::-1])/10 print('str2float(\'123.456\') =', str2float('123.456'))輸出結果
str2float('123.456') = 123.456三、filter
filter() 函數用于過濾序列。接收兩個參數:一個函數和一個序列,filter() 把傳入的函數依次作用于每個元素,然后根據返回值是 True ,則保留,為 False 則丟棄該元素。
def is_odd(n):return n % 2 == 1 print(list(filter(is_odd, [1,2,4,5,6,9,10,15]))) # 結果: [1, 5, 9, 15]==》filter() 函數返回結果是 Iterator,是一個惰性序列,需要使用 list() 函數獲取所有的結果并返回 list。
1、用 filter 求素數
實現方法:埃氏篩法。列出從 2 開始的所有自然數,構造一個序列:取序列第一個數并篩掉其的倍數,依次類推…
# 生成器,且是一個無限序列 def _odd_iter():n = 1while True:n = n + 2yield n# 過濾函數 def _not_divisible(n):return lambda x : x % n > 0# 用于不斷返回素數的生成器 def primes():yield 2it = _odd_iter() # 初始序列while True:n = next(it)yield nit = filter(_not_divisible(n), it) # 構造新的序列# 設置一個退出循環的條件 for n in primes(): if n < 1000:print(n)else:break四、sorted
通常規定,對于兩個元素 x 和 y,如果認為 x < y,則返回-1,如果認為 x == y,則返回 0,如果認為 x > y,則返回 1
1、數字
## 原始 print(sorted([36, 5, -12, 9, -21])) ## sorted()函數也是一個高階函數,它還可以接收一個 key 函數來實現自定義的排序。 ## key 指定的函數將作用于 list 的每一個元素上,并根據 key 函數返回的結果進行排序。 print(sorted([36, 5, -12, 9, -21], key=abs))輸出結果
[-21, -12, 5, 9, 36] [5, 9, -12, -21, 36]2、字符串
## 默認情況下,對字符串排序,是按照 ASCII 的大小比較的 print(sorted(['bob', 'about', 'Zoo', 'Credit'])) ## 可實現忽略大小寫的排序 print(sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower)) ## reverse 為 true 表示反向排序 print(sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower, reverse = True))輸出結果
['Credit', 'Zoo', 'about', 'bob'] ['about', 'bob', 'Credit', 'Zoo'] ['Zoo', 'Credit', 'bob', 'about']五、返回函數
1、函數作為返回值
例如:返回求和的函數
def lazy_sum(*args):def sum():ax = 0for n in args:ax = ax + nreturn axreturn sum f1 = lazy_sum(1,3,5,7,9) f1 f1() # 函數需要調用才能執行 # 調用 lazy_sum()時,每次調用都會返回一個新的函數,即使傳入相同的參數 f2 = lazy_sum(1,3,5,7,9) f1 == f2輸出結果
<function __main__.sum> 25 False分析:在函數 lazy_sum 中又定義了函數 sum,并且,內部函數 sum 可以引用外部函數 lazy_sum 的參數和局部變量,當 lazy_sum 返回函數 sum 時,相關參數和變量都保存在返回的函數中,這種稱為“閉包( Closure) ”的程序結構擁有極大的威力。
2、閉包
返回函數不要引用任何循環變量, 或者后續會發生變化的變量。
3、匿名函數
4、裝飾器
裝飾器”( Decorator):在代碼運行期間動態增加功能的方式。
5、偏函數
模塊
模塊:Python中一個.py文件就是一個模塊(Module)
==》提高了代碼的可維護性;復用性;避免函數名和變量名沖突。
包(Package):按目錄來組織模塊的方法。例如:a.py(a模塊) 與 b.py(b模塊)與其他模塊沖突,則選擇一個頂層包名,例如mycompany,則 a 模塊變成 mycompany.a、b模塊變成 mycompany.b
==》每一個包目錄下面都會有一個__init__.py 的文件,這個文件是必須存在的,用于標識包。
1、使用模塊
#!/usr/bin/env python3 # -*- coding:utf-8 -*-'a test module' ## 表示模塊的文檔注釋,任何模塊代碼的第一個字符串都被視為模塊的文檔注釋__author__ = '盛夏光年'import sysdef test():args = sys.argvif len(args)==1:print("Hello world!")elif len(args) == 2:print('Hello, %s!' % args[1])else:print('Too many arguments!')if __name__ == '__main__':test()2、作用域
- 正常的函數和變量名是公開的( public),可以被直接引用,比如: abc,x123, PI 等;
- 類似__xxx__這樣的變量是特殊變量,可以被直接引用,但是有特殊用途;
- 類似_xxx 和__xxx 這樣的函數或變量就是非公開的( private),不應該被直接引用,比如_abc, __abc 等;
注意: Python 并沒有一種方法可以完全限制訪問 private 函數或變量
3、第三方庫
eg: Pillow、numpy、Jinja2
查看搜索目錄:
添加搜索目錄——方法1:
import sys sys.path.append('/Users/michael/my_py_scripts')==》這種方法是在運行時修改,運行結束后失效。
添加搜索目錄——方法2:
設置環境變量 PYTHONPATH
總結
以上是生活随笔為你收集整理的【Python】编程笔记5的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 金融贷款逾期的模型构建2——集成模型
- 下一篇: 【Python】编程笔记6