摘要:看起來好像是廢話,它還有一個補充的說明,在函數式編程中要避免狀態變化和使用可變對象。函數式編程的特點在中,函數即對象,例如聲明一個函數之后,你可以調用其屬性。
滾雪球學 Python 第四輪,這一番我們要學習點有難度的了,因此,橡皮擦將降低閱讀與理解難度,盡量采用大白話為你鋪墊。
這一輪的學習,非常偏理論,因為涉及的一些概念也是借鑒的其它編程語言的風格,而且實際落地中存在部分爭議
不過多學一點,總是沒有壞處的。
滾雪球學 Python 第四輪,主要學習函數式編程
本系列文章每篇 3000 字左右(包含代碼),所以放心享用,不會增大每日學習強度滴
滾雪球歷史系列,已完成 3 個專欄,更新中 1 個專欄,即第三輪學習更新中,目前到 21 篇~,由于第三輪是項目實踐,學 Django 去,所以第四輪概念類同步開啟。
Python 不是純粹的函數式語言,但你可以使用 Python 進行函數式編程
典型的聽君一席話,如聽一席話,說白了就是 Python 具備函數式編程的特性,
so,可以借用函數式語言的設計模式和編程技術,把代碼寫成函數式編程的樣子
一般此時我會吹噓一下,函數式代碼比較簡潔和優雅~
好了,已經吹噓完了。
以上內容都屬于講道理的范圍,那在 Python 中有哪些適合函數式編程的技能點
又有哪些不適的點呢?
下述 2 點先有個印象就行
reduce
,map
,filter
三巨頭。如果你去百度 “什么是函數式編程”,很多地方會給出答案
函數式編程:允許把函數本身作為參數傳入另一個函數,還允許返回一個函數。
有道理!
其實函數式編程就是在函數中定義表達式和實現表達式的求職,說白了就是用函數落地你的代碼。
看起來好像是廢話,它還有一個補充的說明,在函數式編程中要避免狀態變化和使用可變對象。
其中避免狀態變化 重點要關注賦值語句以及它如何改變狀態,因此你在函數式編程中,不會看到 global
,nolocal
等內容。
概念與原理都是比較抽象的,咱還是少說概念,這個留到未來你自己總結就好,直接展示源碼差異。
計算 1~100 內,計算 5 與 7 的倍數之和
面向過程的寫法
count = 0for num in range(1, 101): if num % 5 == 0 or num % 7 == 0: count += numprint(count)
在面向過程的寫法中,邏輯都是從上向下進行運行的,例如 num
從 1 數到 100,如果對 5 或者對 7 取余等于 0,那表示可以整除,然后將 count
與對應的 num
相加,得到最后的余數。
這種思路是純面向過程的寫法,一般我們學習編程時,首先學會的就是該類寫法。
面向對象的寫法
該類寫法有兩種,一種是使用 Python 內置的列表實現,一種是自己聲明一個類來實現。
第一種寫法:
count = list()for num in range(1, 101): if num % 5 == 0 or num % 7 == 0: count.append(num)print(sum(count))
在上述寫法中,變量 count
聲明一個 list
,即列表對象,但是整理看起來還是有些過程式編程語言的影子。
例如最后的 sum(count)
的使用就有些奇怪,看不出來面向對象的影子。
接下來,咱們創建一個自定義的類,進行邏輯實現。
class My_List_Sum(list): def sum(self): count = 0 for n in self: count += n return countcount = My_List_Sum()for num in range(1, 101): if num % 5 == 0 or num % 7 == 0: count.append(num)print(count.sum())
上述代碼,我們自行實現了一個 My_List_Sum
類,讓它繼承自 list
,此時你應該明白,list
就是一個類名,然后在類的內部實現了 sum
方法,再調用該對象的 sum
方法,完美的應用了面向對象的寫法。
接下來進入正題,函數式編程的落地實現
在正式編寫前,需要回憶一些基礎知識,例如 lambda
表達式以及列表相加。
判斷一個數字是 5 或者 7 的倍數, lambda
寫法如下:
multiple = lambda x: x % 5 == 0 or x % 7 == 0a = multiple(3) # Falseb = multiple(5) # Truec = multiple(7) # Falseprint(a, b, c)
列表相加代碼如下:
print([1]+[2]) # [1,2]
有了上述內容,可以編寫一個遞歸函數,實現對應的邏輯,代碼的說明已經添加到注釋中。
def tool(n: int, end: int, filter_func) -> list: """返回一個篩選之后的列表 :param n: 起始值 :param end: 終止值 :param filter_func: 判斷表達式 """ # 如果到達上限,直接返回空列表 if n == end: return [] # 如果滿足過濾條件,返回該值與下一個值組成的列表 if filter_func(n): return [n] + tool(n + 1, end, filter_func) else: # 不滿足過濾條件,直接返回下一個值 return tool(n + 1, end, filter_func)# 測試代碼ret = tool(1, 101, lambda x: x % 5 == 0 or x % 7 == 0)print(ret)print(sum(ret))
上述代碼即為求和的函數式實現,其中部分邏輯如下:
當然還有一種函數式編程的寫法,代碼如下:
print(sum(n for n in range(1, 101) if n % 5 == 0 or n % 7 == 0))
這里用到的生成器后文會進行說明。
在 Python 中,函數即對象,例如聲明一個函數之后,你可以調用其屬性。
下述代碼展示的即為函數對象的屬性,其余內容可以自行再做測試。
def my_func(var1, var2, **kw): return var1 + var2print(type(my_func)) # print(my_func.__code__)print(my_func.__dict__)print(my_func.__code__.co_code)print(my_func.__code__.co_filename)print(my_func.__code__.co_argcount)
函數式編程之所以高效,其中一個很重要的原因就是延遲計算,也叫做惰性求值,這些在后面都將逐步展開,現在依舊是接收一下印象概念。
正是因為函數即對象,所有才有本文開篇那段對函數式編程的定義。
函數可以使用其它函數作為參數,或者返回另一個函數,所以在實際編碼過程中,我們將會把函數轉換成其它代碼中的 “對象”,從而實現函數式編程。
接下來咱們要接觸一下 Python 中的純函數概念以及應用。
純函數是一個概念,也就是讓函數不會對函數外作用域產生影響,即作用域為本地。
說簡單點,就是在函數內部避免賦值操作,當然類似 global
等關鍵字也避免使用。
針對此,lambda
表達式就是純函數。
首先查看一個純函數的例子:
def my_func(num: int) -> int: return num * 100
上述代碼中函數的返回值僅與 num
有關,滿足下面兩個條件:
接觸完畢純函數概念之后,下面了解一下函數作為對象的落地應用。
在 Python 中聲明一個類,默認會攜帶部分內置的方法,例如:
from typing import Callable# 聲明一個類,該類無意義,僅測試使用class Ext: # 傳入的函數,可攜帶1~2個參數 def __init__(self, test_demo: Callable[[int], int]) -> None: self.func = test_demo # 返回結果擴大2倍 def __call__(self, arg: int) -> int: return self.func(arg) * 2def one_func(var): return var + 1def two_func(var): return var * 3def three_func(var): return vara = Ext(one_func)print(a(3)) # 8b = Ext(two_func)print(b(3)) # 18c = Ext(three_func)print(c(3)) # 6
上述代碼使用了一個新的模塊 typing
,該模塊是 Python 3.5 之后新增的模塊,主要為 Python 提供靜態類型的檢查 。
本案例中導入的是回調函數 Callable
,格式如下:
Callable[[Arg1Type, Arg2Type],ReturnType]
其中內部中括號 Arg1Type
是參數類型,ReturnType
為返回值類型。
上述三個函數的簽名都與 Callable
定義的一致,所以都可以作為 test_demo
參數的值去傳遞。
滾雪球學Python第四輪,非常理論的一個系列,跟上大部隊的節奏,走起來,有任何問題,都可以在評論區留言,一般1小時之內都能解決。
今天是持續寫作的第 213 / 365 天。
可以關注,點贊、評論、收藏。
更多精彩
太多了,去主頁看吧。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119554.html
摘要:圖片下載屬于操作,比較耗時,基于此,可以利用中的多線程將其實現。更多精彩滾雪球學完結滾雪球學第二輪完結滾雪球學第三輪滾雪球學番外篇完結 在 python 編碼過程中...
摘要:的安裝博客補充知識年最新安裝教程,滾雪球學第四季。操作操作數據庫一般被程序員成為操作增刪改查,其中各個字符分別代表新增,讀取,更新,刪除。可以返回受影響行數,可以直接通過該值判斷是否修改成功。 ...
摘要:盡管如此,還具有高級的數據類型和靈活性。它配備了大量的標準模塊,可用于程序庫。一些模塊提供如下功能通過這些很贊的特性,瞬時化身為面向過程的語言。開發者可以便捷地將解釋器連接到一個使用編寫的應用程序,并能隨時用作擴展。下一部分會繼續分享。 【編者按】本文作者是 Abhishek Jaiswal ,擅長 .NET、C#、Python 等多種語言的技術控。本文中,作者通過活潑有趣的口吻向大家...
摘要:項目地址中的函數式編程函數式編程英語或稱函數程序設計,又稱泛函編程,是一種編程范型,它將電腦運算視為數學上的函數計算,并且避免使用程序狀態以及易變對象。 項目地址:https://git.io/pytips Python 中的函數式編程 函數式編程(英語:functional programming)或稱函數程序設計,又稱泛函編程,是一種編程范型,它將電腦運算視為數學上的函數計算,并且...
摘要:遞歸函數遞歸函數的用法遞歸函數在一個函數里在調用這個函數本身。如來根本不會管師徒四人按照什么流程去取。面向對象的程序優點是解決了程序的擴展性。 遞歸函數 遞歸函數的用法: - 遞歸函數:在一個函數里在調用這個函數本身。 - 遞歸的最大深度:998 實例 找一個函數的索引位置,遞歸實現 l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,5...
閱讀 1015·2021-09-26 09:55
閱讀 3555·2021-09-24 10:30
閱讀 1364·2021-09-08 09:36
閱讀 2552·2021-09-07 09:58
閱讀 603·2019-08-30 15:56
閱讀 764·2019-08-29 18:32
閱讀 3592·2019-08-29 15:13
閱讀 1840·2019-08-29 13:49