您好,登錄后才能下訂單哦!
[TOC]
? 很多初學者在了解了一門編程語言的基本語法和使用之后,面對一個’開發需求‘時仍然會覺得無從下手、沒有思路/套路,本節主題“編程范式”正是為了解決該問題,那到底什么是編程范式呢?
編程范式指的就是編程的套路,打個比方,如果把編程的過程比喻為練習武功,那編程范式指的就是武林中的各種流派,而在編程的世界里常見的流派有:面向過程、函數式、面向對象等,本節我們主要介紹前兩者。
? 在正式介紹前,我們需要強調:“功夫的流派沒有高低之分,只有習武的人才有高低之分“,在編程世界里更是這樣,各種編程范式在不同的場景下都各有優劣,誰好誰壞不能一概而論,下面就讓我們來一一解讀它們。
插圖:惡搞圖62
? ”面向過程“核心是“過程”二字,“過程”指的是解決問題的步驟,即先干什么再干什么......,基于面向過程開發程序就好比在設計一條流水線,是一種機械式的思維方式,這正好契合計算機的運行原理:任何程序的執行最終都需要轉換成cpu的指令流水按過程調度執行,即無論采用什么語言、無論依據何種編程范式設計出的程序,最終的執行都是過程式的。
插圖:惡搞圖63
? 詳細的,若程序一開始是要著手解決一個大的問題,按照過程式的思路就是把這個大的問題分解成很多個小問題或子過程去實現,然后依次調用即可,這極大地降低了程序的復雜度。舉例如下:
? 寫一個數據遠程備份程序,分三步:本地數據打包,上傳至云服務器,檢測備份文件可用性
import os,time
# 一:基于本章所學,我們可以用函數去實現這一個個的步驟
# 1、本地數據打包
def data_backup(folder):
print("找到備份目錄: %s" %folder)
print('正在備份...')
zip_file='/tmp/backup_%s.zip' %time.strftime('%Y%m%d')
print('備份成功,備份文件為: %s' %zip_file)
return zip_file
# 2、上傳至云服務器
def cloud_upload(file):
print("\nconnecting cloud storage center...")
print("cloud storage connected")
print("upload [%s] to cloud..." %file)
link='https://www.xxx.com/bak/%s' %os.path.basename(file)
print('close connection')
return link
#3、檢測備份文件可用性
def data_backup_check(link):
print("\n下載文件: %s , 驗證文件是否無損..." %link)
# 二:依次調用
# 步驟一:本地數據打包
zip_file = data_backup(r"/Users/egon/歐美100G高清無碼")
# 步驟二:上傳至云服務器
link=cloud_upload(zip_file)
# 步驟三:檢測備份文件的可用性
data_backup_check(link)
插圖:惡搞圖64
面向過程總結:
1、優點
將復雜的問題流程化,進而簡單化
2、缺點
'''
程序的可擴展性極差,因為一套流水線或者流程就是用來解決一個問題,就好比生產汽水的流水線無法生產汽車一樣,即便是能,也得是大改,而且改一個組件,與其相關的組件可能都需要修改,比如我們修改了cloud_upload的邏輯,那么依賴其結果才能正常執行的data_backup_check也需要修改,這就造成了連鎖反應,而且這一問題會隨著程序規模的增大而變得越發的糟糕。
'''
def cloud_upload(file): # 加上異常處理,在出現異常的情況下,沒有link返回
try:
print("\nconnecting cloud storage center...")
print("cloud storage connected")
print("upload [%s] to cloud..." %file)
link='https://www.xxx.com/bak/%s' %os.path.basename(file)
print('close connection')
return link
except Exception:
print('upload error')
finally:
print('close connection.....')
def data_backup_check(link): # 加上對參數link的判斷
if link:
print("\n下載文件: %s , 驗證文件是否無損..." %link)
else:
print('\n鏈接不存在')
3、應用場景
面向過程的程序設計一般用于那些功能一旦實現之后就很少需要改變的場景, 如果你只是寫一些簡單的腳本,去做一些一次性任務,用面向過程去實現是極好的,但如果你要處理的任務是復雜的,且需要不斷迭代和維護, 那還是用面向對象最為方便。
插圖:惡搞圖65
函數式編程并非用函數編程這么簡單,而是將計算機的運算視為數學意義上的運算,比起面向過程,函數式更加注重的是執行結果而非執行的過程,代表語言有:Haskell、Erlang。而python并不是一門函數式編程語言,但是仍為我們提供了很多函數式編程好的特性,如lambda,map,reduce,filter
插圖:惡搞圖66
? 對比使用def關鍵字創建的是有名字的函數,使用lambda關鍵字創建則是沒有名字的函數,即匿名函數,語法如下
lambda 參數1,參數2,...: expression
舉例
# 1、定義
lambda x,y,z:x+y+z
#等同于
def func(x,y,z):
return x+y+z
# 2、調用
# 方式一:
res=(lambda x,y,z:x+y+z)(1,2,3)
# 方式二:
func=lambda x,y,z:x+y+z # “匿名”的本質就是要沒有名字,所以此處為匿名函數指定名字是沒有意義的
res=func(1,2,3)
插圖:惡搞圖67
匿名函數與有名函數有相同的作用域,但是匿名意味著引用計數為0,使用一次就釋放,所以匿名函數用于臨時使用一次的場景,匿名函數通常與其他函數配合使用,我們以下述字典為例來介紹它
salaries={
'siry':3000,
'tom':7000,
'lili':10000,
'jack':2000
}
要想取得薪水的最大值和最小值,我們可以使用內置函數max和min(為了方便開發,python解釋器已經為我們定義好了一系列常用的功能,稱之為內置的函數,我們只需要拿來使用即可)
>>> max(salaries)
'tom'
>>> min(salaries)
'jack'
內置max和min都支持迭代器協議,工作原理都是迭代字典,取得是字典的鍵,因而比較的是鍵的最大和最小值,而我們想要的是比較值的最大值與最小值,于是做出如下改動
# 函數max會迭代字典salaries,每取出一個“人名”就會當做參數傳給指定的匿名函數,然后將匿名函數的返回值當做比較依據,最終返回薪資最高的那個人的名字
>>> max(salaries,key=lambda k:salaries[k])
'lili'
# 原理同上
>>> min(salaries,key=lambda k:salaries[k])
'jack'
同理,我們直接對字典進行排序,默認也是按照字典的鍵去排序的
>>> sorted(salaries)
['jack', 'lili', 'siry', 'tom']
插圖:惡搞圖68
函數map、reduce、filter都支持迭代器協議,用來處理可迭代對象,我們以一個可迭代對象array為例來介紹它們三個的用法
array=[1,2,3,4,5]
要求一:對array的每個元素做平方處理,可以使用map函數
map函數可以接收兩個參數,一個是函數,另外一個是可迭代對象,具體用法如下
>>> res=map(lambda x:x**2,array)
>>> res
<map object at 0x1033f45f8>
>>>
解析:map會依次迭代array,得到的值依次傳給匿名函數(也可以是有名函數),而map函數得到的結果仍然是迭代器。
>>> list(res) #使用list可以依次迭代res,取得的值作為列表元素
[1, 4, 9, 16, 25]
插圖:惡搞圖69
要求二:對array進行合并操作,比如求和運算,這就用到了reduce函數
reduce函數可以接收三個參數,一個是函數,第二個是可迭代對象,第三個是初始值
# reduce在python2中是內置函數,在python3中則被集成到模塊functools中,需要導入才能使用
>>> from functools import reduce
>>> res=reduce(lambda x,y:x+y,array)
>>> res
15
解析:
1 沒有初始值,reduce函數會先迭代一次array得到的值作為初始值,作為第一個值數傳給x,然后繼續迭代一次array得到的值作為第二個值傳給y,運算的結果為3
2 將上一次reduce運算的結果作為第一個值傳給x,然后迭代一次array得到的結果作為第二個值傳給y,依次類推,知道迭代完array的所有元素,得到最終的結果15
也可以為reduce指定初始值
>>> res=reduce(lambda x,y:x+y,array,100)?>>> res
115
要求三:對array進行過濾操作,這就用到了filter函數,比如過濾出大于3的元素
>>> res=filter(lambda x:x>3,array)
解析:filter函數會依次迭代array,得到的值依次傳給匿名函數,如果匿名函數的返回值為真,則過濾出該元素,而filter函數得到的結果仍然是迭代器。
>>> list(res)
[4, 5]
提示:我們介紹map、filter、reduce只是為了帶大家了解函數式編程的大致思想,在實際開發中,我們完全可以用列表生成式或者生成器表達式來實現三者的功能。
插圖:惡搞圖70
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。