天天看點

Python進階文法——函數式程式設計——學習心得筆記Python進階文法——函數式程式設計——學習心得筆記1. 函數式程式設計(FunctionalProgramming)

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模式下,遇到斷點就會暫停

繼續閱讀