Python進階文法——函數式程式設計——學習心得筆記
1. 函數式程式設計(FunctionalProgramming)
1.1. 基于lambda演算的一種程式設計方式
- 程式中隻有函數
- 函數可以作為參數,同樣可以作為傳回值
- 純函數式程式設計語言:LISP, Haskell
- Python函數式程式設計隻是借鑒函數式程式設計的一些特點,可以了解為一半函數式一半Python
- 常用函數
- 高階函數
- 傳回函數
- 匿名函數
- 裝飾器
- 偏函數
- lambda表達式
- 函數:最大程度複用代碼
- 存在問題: 如果函數很小很短,則會造成啰嗦
- 如果函數被調用次數少,則會造成浪費
- 對于閱讀者來說,造成閱讀流程的被迫中斷
- 看執行個體 小函數
- lambda表達式(匿名函數)
- 一個表達式,函數體相對簡單
- 不是一個代碼塊,僅僅是一個表達式
- 可以有參數,有多個參數也可以,用逗号隔開
- 看執行個體
1.2. 高階函數
- 把函數作為參數使用的函數,叫高階函數
- 看執行個體
- 系統高階函數
- map: 映射
-
即把集合或者清單中的元素,每一個元素都按照一定的規則進行操作,生成一個新的
清單或者集合
- map函數是系統提供的具有映射功能的高階函數,傳回值是一個疊代對象
- 看執行個體
-
- reduce: 歸并,縮減
- 把一個可疊代的對象最後歸并成一個結果
- 對于函數參數有要求:
-
必須有兩個參數,必須有傳回結果
= 看執行個體
- filter: 過濾函數
- 對一組資料進行過濾,符合條件的資料會生成一個新的清單并傳回
- 看執行個體
- 排序
- python内置函數(sort()、sorted()、argsort()
- 高階函數排序:把一個序列按照給定算法進行排序
- 傳回函數
- 函數作為函數值傳回
- 看執行個體
-
閉包(closure)
**
執行個體
**
# Python進階文法——函數式程式設計
# '小'函數舉例
def printA():
print("AAAAA")
printA()
# lambda表達式(匿名函數)
# 以lambda開頭
# 緊跟一定的參數,如果有的話
# 參數後用冒号和表達式主題隔開
# 隻是一個表達式,是以沒有return
# 計算一個數字的100倍
stm = lambda x: 100 * x
# 使用上跟調用函數一模一樣
print(stm(100))
# 下式也可以定義為一個函數,傳回一個值,但是表達式會比這個複雜的多
stm1 = lambda x, y, z: x + y * 10 + z * 100
print(stm1(4, 5, 6))
# 高階函數,函數作為參數使用的函數
# 函數名稱就是一個變量
def funA():
print("In funA")
funB = funA
funA()
funB()
# 高階函數舉例
# funA是普通函數,傳回一個傳入數字的100倍的數字
def funA(n):
return n * 100
# 在寫一個普通函數,把傳入的函數乘以300倍
def funB(n):
return funA(n) * 3
print(funB(9))
# 寫一個高階函數,f = funA
def funC(n, f):
# 假定函數是把n擴大100倍
return f(n) * 3
print(funC(9, funA))
# 比較funC和funB,顯熱funC更靈活
# 例如n現在要放大30倍
# 如果要調用funB,需要修改funB的函數本體
def funD(n):
return n * 10
print(funC(9, funD))
# map映射執行個體
l1 = [i for i in range(10)]
print(l1)
l2 = []
for i in l1:
l2.append(i * 10)
print(l2)
# map實作上述功能
l1 = [i for i in range(10)]
def mulTen(n):
return n * 10
l3 = map(mulTen, l1)
for i in l3:
print(i)
print(l3)
# reduce執行個體
from functools import reduce
def myAdd(x, y):
return x + y
# 對于清單[1, 2, 3, ....]執行,前一個加一個一直結束傳回一個值
# 1到100的數字相加
rst = reduce(myAdd, [i for i in range(101)])
print(rst)
# filter函數
# 定義過濾函數
# 過濾函數要求有輸入,傳回布爾值
def isEven(a):
return a % 2 == 0
l = [3, 3, 3, 45, 23, 54, 63, 24, 67, 5, 5, 6, 9, 8, 8]
rst = filter(isEven, l)
print(type(rst))
print(rst)
# 傳回的就是filter資料,資料都進行了包裝
# 采用for循環提取資料
print([i for i in rst])
# 排序案例
l = [3, 45, -7, 23, 54, -43, -78, 63, 24, 67, -120, 5, 6, 9, 8]
# 正序
al = sorted(l)
print(al)
# 倒序
al = sorted(l, reverse=True)
print(al)
# 按照絕對值排序
al = sorted(l, key=abs, reverse=True)
print(al)
# sorted案例
astr = ['abc', 'Tian', 'hafj', 'Xixi']
str1 = sorted(astr)
print(str1)
str2 = sorted(astr, key=str.lower)
print(str2)
# 函數作為值傳回
def myF2():
def myF3():
print("In myF3")
return 3
return myF3
f3 = myF2()
print(type(f3))
print(f3)
1.3. 裝飾器(decrator)
- 在不改動函數代碼的基礎上次無限擴充函數功能的一種機制
- 本質上講,裝飾器是一個傳回函數的高階函數
- 裝飾器文法:
- 使用@文法,即在每次要擴充到函數定義前使用@+函數名
- 看執行個體23_2.py
- 裝飾器的好處:
- 一旦定義,則可以裝飾任意函數
-
一旦被其裝飾,則把裝飾器的功能直接添加到定義的函數上
**
執行個體23_2
**
# 裝飾器
# 對hello函數進行擴充
# 高階函數,以函數作為參數
import time
def printTime(f):
def wrapper(*args, **kwargs):
print("Time: ", time.ctime())
return f(*args, **kwargs)
return wrapper()
# 上面定義了一個裝飾器。調用需要使用@
# hello函數就進行了擴充
@printTime
def hello():
print("Hello world!")
hello
@printTime
def hello1():
print("Hello world!")
hello1
# 偏函數
# 把字元串轉化為十進制數字
l = int("12345")
# print(l)
# 求八進制的字元串12345,表示成十進制的數字是多少
l = int("12345", base=8)
# print(l)
# 建立一個函數,函數預設輸入的是的字元串是16進制的數字
# 把此字元串轉化成十進制和八進制的數字
def int16(x, base=16):
return int(x, base)
print(int16("12345"))
def int10(x, base=16):
return int(x, base=8)
print(int10("12345"))
# 偏函數
import functools
# 實作上面int16的功能
int16 = functools.partial(int, base=16)
print(int16("12345"))
# 進階函數補充
# zip執行個體
l1 = [1, 2, 3, 4, 5]
l2 = [11, 22, 33, 44, 55]
l3 = zip(l1, l2)
print(type(l3))
print(l3)
for i in l3:
print(i)
l1 = ['zhangfei', 'lisi', 'zhuergou']
l2 = [56, 76, 98]
l3 = zip(l1, l2)
for i in l3:
print(i)
# enumerate執行個體
# 每個值添加一個索引
l1 = [1, 2, 3, 4, 5]
em = enumerate(l1)
l2 = [i for i in em]
print(l2)
em = enumerate(l1, start=100)
l2 = [i for i in em]
print(l2)
1.4. 偏函數
- functools.partial()
- 作用:把一個函數的某些函數或者參數固定,傳回一個新函數
- 看執行個體
1.5. 進階函數補充
- zip 把兩個可疊代内容生成一個可疊代的tuple元素類型組成的内容
- enumerate 根zip功能很像,可疊代對象裡的每一個元素,配上一個索引,然後索引和内容構成一個tuple類型
- collection
- namedtuple: 是一個可命名的tuple
- deque: 解決了頻繁删除和插入帶來的效率問題
- defaultdict: 當直接讀取dict不存在的屬性時,直接傳回預設值
- counter: 統計字元串中每個字元出現的個數,并傳回一個字典
-
看執行個體23_3.py
執行個體23_3
# collection子產品
# namedtuple
import collections
# help(collections.namedtuple)
# 定義一個點
Point = collections.namedtuple("Point", ['x', 'y'])
p = Point(11, 12)
print(p.x)
print(p.y)
print(p[0])
print(p[1])
# 定義一個圓
Circle = collections.namedtuple("Circle",['x', 'y', 'r'])
c = Circle(100, 150, 50)
print(c)
print(c.x)
print(type(c))
# c是不是一個tuple(元組)
i = isinstance(c, tuple)
print(i)
# dequeue
from collections import deque
q = deque(['a', 'b', 'c'])
print(q)
q.append('d')
q.appendleft('x')
print(q)
# defaultdict
from collections import defaultdict
func = lambda: "Felix"
d2 = defaultdict(func)
print(d2['one'])
print(d2['four'])
# Counter統計每個字元出現的個數,傳回字典
from collections import Counter
c = Counter('abcfeafffefaljdfjakdjkdjdkkd')
print(c)
1.6. 調試技術
- 調試流程:單元測試->內建測試->交測試部
- 分類:
- 靜态調試:
- 動态調試:
- pycharm調試
- run: 全部運作模式
- debug: 調試模式
- 斷點:程式的某一行,程式在debug模式下,遇到斷點就會暫停