面向過程:根據業務邏輯從上到下壘代碼python
函數式:將某功能代碼封裝到函數中,往後便無需重複編寫,僅調用函數便可編程
函數做用是你的程序有良好的擴展性、複用性。服務器
一樣的功能要是用3次以上的話就建議使用函數。數據結構
特殊理解:閉包
函數能夠理解爲一個一個的功能塊,你把一個大的功能拆分紅一塊一塊的,用某項功能的時候就去調用某個功能塊便可!app
函數能夠理解爲:樂高積木,給你一塊一塊的,你能夠用這些積木塊組成你想要的任何功能!函數式編程
函數能夠調用函數!主函數的做用就是把函數進行串聯、調用!函數自己是不能本身執行的若是不調用就永不執行!函數
#---------------------------------------------------
def func1():
pass
def func2(): pass def func3(): pass def func4(): pass func1() func2() func3() func4() if __name__ == '__main__': #調用上面的函數,判斷了、循環了調用等! #函數裏也能夠調用函數例子:def func4(): #__name__ 這個是用來判斷,若是你是把這個程序當模塊導入的話它的__name__就等於這個程序的文件名,若是是手動執行這個腳本好比:python test.py 那麼__name__就等於__main__ 因此,咱們能夠用他來作判斷,若是你是手動執行我就調用函數執行if下面的語句,若是你是調用模塊下面的if判斷後面的語句就不執行!僅當模塊使用! #若是函數當模塊導入的時候,他導入的是函數的名稱,內容沒有被導入,當你去調用的時候他纔會導入函數裏的信息。
在學習函數以前,一直遵循:面向過程編程,即:根據業務邏輯從上到下實現功能,其每每用一長段代碼來實現指定功能,開發工程中比較常見的操做就是粘貼複製,也就是將以前實現的代碼塊複製到現需功能處,以下:學習
while True:
if cpu利用率 > 90 %: # 發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接 if 硬盤使用空間 > 90%: # 發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接 if 內存佔用 >80%: # 發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接
上面的代碼就是面向過程的編程,可是若是報警多了的話成百的代碼須要如何操做呢?複製粘貼就會顯得本身low,該如何編寫呢,請看下面的代碼:測試
def 發送郵件(內容)
#發送郵件提醒
鏈接郵箱服務器 發送郵件 關閉鏈接 while True: if cpu利用率 > 90%: 發送郵件('CPU報警') if 硬盤使用空間 > 90%: 發送郵件('硬盤報警') if 內存佔用 > 80%: 發送郵件('內存報警')
第二個必然比第一個的重用性和可讀性要好,其實就是函數式編程和麪向過程編程的區別:
● 面向過程:更具需求一行一行壘加代碼!邏輯亂、並切代碼重複、不易修改重用性差!
● 函數式:將某功能代碼封裝到函數中,往後便無需重複編寫,僅調用函數便可
● 面向對象:對函數進行分類和封裝,讓開發"更快更好更強"
# 語法
def 函數(參數1,參數2,參數3,....):
' ' '註釋' ' ' 函數體 return 返回的值 #函數名的定義要能反映其意義
函數的定義主要有以下要點:
● def 表示函數的關鍵字
● 函數名:函數的名稱,往後根據函數名調用函數
● 參數:爲函數體提供數據
● 函數體:函數中進行一系列的邏輯計算,如,發送郵件、計算出[11,22,45,56,45,]中的最大數等....
● 返回值:當函數執行完畢後,能夠給調用者返回數據。
函數即"變量","變量"必須先定義後引用,未定義而直接函數,就至關於在引用一個不存在的變量名 #測試一 def func(): print('from foo') bar() func() #報錯 #測試二 def abc(): print('from abc') def func(): print('from func') abc() func() #正常 #測試三 def func(): print('from func') abc() def abc(): print('from abc') func() #不會報錯 #結論:函數的使用,必須遵循原則:先定義,後調用 #咱們在使用函數時,必定要明確的區分定義階段和調用階段 #定義階段: def func(): print('from func') abc() def abc(): print('from abc') #調用階段 func()
#只檢測語法,不執行代碼 也就說,語法錯誤在函數定義階段就會檢測出來,而代碼的邏輯錯誤只有在執行的時候纔會知道
#一、無參:應用場景僅僅只是執行一些操做,好比與用戶交互,打印 #二、有參:須要根據外部傳進來的參數,才能執行相應的邏輯,好比統計長度,求最大值最小值 #三、空函數:設計代碼結構
一、返回值
函數式一個功能塊,該功能到底執行成功與否,須要經過返回值來告知調用者。
def test():
'''
2*x+1
:param x:整形數字
:return: 返回計算結果
''' x=3 y=2*x+1 return y a = test() print(a)
def 發送短信():
發送短信的代碼..:
if 發送成功: return True else: return False while True: # 每次執行發送短信函數,都會將返回值自動賦值給result # 以後,能夠根據result來寫日誌,或重發等操做 result = 發送短信() if result == False: 記錄日誌,短信發送失敗....
二、參數
一、形參與實參
#形參即變量名,實參即變量值,函數調用時,將值綁定到變量名上,函數調用結束,解除綁定
二、具體應用
#一、位置參數:按照從左到右的順序定義的參數
位置形參:必選參數
位置實參:按照位置給形參傳值
#二、關鍵字參數:安裝key=value的形式定義的實參
無需按照位置爲形象傳值 注意的問題: 1、關鍵字實參必須在位置實參右面 2、對同一個形參不能重複傳值 #三、默認參數:形參在定義時就已經爲其賦值 能夠傳值也能夠不傳值,常常須要變得參數定義成位置形參,變成較小的參數定義成默認參數(形參) 注意的問題: 1、只在定義時賦值一次 2、默認參數的定義應該在位置形參右面 3、默認參數一般應該定義成不可變類型 #四、可變長參數: 可變長指的是實參值的個數不固定 而實參有按位置和按關鍵字兩種形式定義,針對這兩種形式的可變長,形參對應有兩種解決方案來完整地存放它們,分別是*args,**kwargs # ########### *args #################### def foo(x,y,*args): print(x,y) print(args) foo(1,2,3,4,5) 輸出結果: C:\Python35\python3.exe C:/Users/ZR/PycharmProjects/python全棧開發/day15/def函數.py 1 2 (3, 4, 5) def foo(x,y,*args): print(x,y) print(args) foo(1,2,*[3,4,5]) 輸出結果: 1 2 (3, 4, 5) def foo(x,y,z): print(1,2,3) foo(*[1,2,3]) 輸出結果: 1 2 3 # ############ **kwargs ################### def foo(x,y,**kwargs): print(x,y) print(kwargs) foo(1,y=2,a=1,b=2,c=3) 輸出結果: 1 2 {'c': 3, 'a': 1, 'b': 2} def foo(x,y,**kwargs): print(x,y) print(kwargs) foo(1,y=2,**{'a':1,'b':2, 'c':3}) 輸出結果: #更上面輸出結果相同,只不過位置有所變化 1 2 {'a': 1, 'b': 2, 'c': 3} def foo(x,y,z): print(x, y, z) foo(**{'z':1,'x':2,'y':3}) 輸出結果: 2 3 1 # ##### *args + **kwargs############ def foo(x,y): print(x,y) def wrapper(*args,**kwargs): print('==========>') foo(*args,**kwargs) #五、命名關鍵字參數:*後定義的參數,必須被傳值(有默認值的除外),且必須按照關鍵字實參的形式傳遞 def foo(x,y,*args,a=1,b,**kwargs): print(x,y) print(args) print(a) print(b) print(kwargs) foo(1,2,3,4,5,b=3,c=4,d=5) 輸出結果: 1 2 (3, 4, 5) 1 3 {'c': 4, 'd': 5}
爲何要用參數?舉例說明
若是不定義參數,用函數的話:(每一個有相同功能的都寫個函數,說好的代碼簡化呢?)
def cpu報警郵件():
# 發送郵件提醒
鏈接郵箱服務器 發送郵件 關閉鏈接 def 硬盤報警郵件(): # 發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接 def 內存報警郵件(): # 發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接 while True: if CPU利用率 > 90%: cpu報警郵件() if 硬盤使用空間 > 90%: 硬盤報警郵件() if 內存佔用 > 80%: 內存報警郵件()
使用函數:(代碼明顯少了不少,把重複內用改成參數調用!)
def 發送郵件(內容)
#發送郵件提醒
鏈接郵箱服務器 發送郵件 關閉鏈接 while True: if cpu利用率 > 90%: 發送郵件('CPU報警') if 硬盤使用空間 > 90%: 發送郵件('硬盤報警') if 內存佔用 > 80%: 發送郵件('內存報警')
函數的四種不一樣的參數:
一、普通參數
二、默認參數
三、動態參數
# #### 定義函數 ###############
# name 叫作函數func的形式參數,簡稱:形參
def func(name):
print(name) # #### 執行函數 ############### # 'zhurui' 叫作函數func的實際參數,簡稱:實參 func('zhurui')
可是普通參數有個問題!你在定義參數的時候定義了幾個參數,你在調用的時候必須給他幾個參數不然會報錯!
def func(name,age):
print(name,age) func('william') 報錯提示: TypeError: func() missing 1 required positional argument: 'age' 其正確的寫法是: def func(name,age): print(name,age) func('william',24) 輸出結果: william 24
在你沒有給他指定參數的時候它就會使用默認參數!
def func(name, age = 24):
print('%s:%s' %(name,age)) # 指定參數: func('william', 32) 輸出結果: william:24 # 使用默認參數 func('william') 輸出結果: william:27
在子程序中定義的變量成爲局部變量,在程序的一開始定義的變量稱爲全局變量。
全局變量做用域是整個程序,局部變量做用域是定義該變量的子程序。
當全局變量與局部變量同名時:
在定義局部變量的子程序內,局部變量起做用;在其餘地方全局變量起做用。
name='simon' #全局變量 def change_name(): name='牛逼的人物' #局部變量 print('change_name',name) change_name() print(name) 輸出結果: C:\Python35\python3.exe G:/python_s3/day15/全局變量與局部變量.py change_name 牛逼的人物 simon #輸出結果要想讓全局變量改變成局部變量須要在做用域中加 global name,至關於指針跟引用 代碼以下: name='simon' #全局變量 def change_name(): global name name='牛逼的人物' #局部變量 print('change_name',name) change_name() print(name) 輸出結果: C:\Python35\python3.exe G:/python_s3/day15/全局變量與局部變量.py change_name 牛逼的人物 牛逼的人物
name = 'simon' def test1(): #name = '孫悟空' global name #將全局變量引用過來,已經聲明,name就是全局的那個變量 print('我要搞', name) def test2(): name = '基' print('我要搞', name) #若是函數的內部無 global關鍵字,優先讀取局部變量,能讀取全局變量,沒法對全局變量從新賦值 NAME='fff',可是對於可變類型,能夠對內部元素進行操做 #若是函數中有global關鍵字,變量本質上就是全局的那個變量,可讀取可賦值 test1() test2()
注意:
全局變量變量名大寫
局部變量變量名小寫
def huangwei(): name = '黃偉' print(name) def liuyang(): name = '劉洋' print(name) def nulige(): name = '滬指花' print(name) print(name) nulige() liuyang() print(name) huangwei()
def weihou(): name = "陳卓" def weiweihou(): global name name = "冷靜" weiweihou() print(name) print(name) weihou() print(name) 輸出結果: C:\Python35\python3.exe G:/python_s3/day15/全局變量與局部變量.py 剛娘 陳卓 冷靜
代碼運行示例圖:
使用nonlocal 指定上一級變量
name = "剛娘" def weihou(): name = "陳卓" def weiweihou(): nonlocal name #nonlocal,指定上一級變量 name = "冷靜" weiweihou() print(name) print(name) weihou() print(name) 運行結果: C:\Python35\python3.exe G:/python_s3/day15/全局變量與局部變量.py 剛娘 冷靜 剛娘
在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身
def calc(n): print(n) if int(n/2) == 0: return n return calc(int(n/2)) calc(10) 輸出結果: C:\Python35\python3.exe G:/python_s3/day15/全局變量與局部變量.py 10 5 2 1
__author__ = 'zhurui' import time person_list=['zhurui','caiyunjie','yuanhao','simon','william','zcz'] def ask_way(person_list): print('-'*60) if len(person_list) == 0: return '沒人知道' person=person_list.pop(0) if person == 'simon': return '%s說:我知道,東方財富網就在東方財富大廈A座,下肇嘉浜路地鐵站就是' %person print('hi 美男[%s],敢問路在何方' % person) print('%s回答道:我不知道,但你慧眼識珠,我去幫你問問%s...' % (person,person_list) ) time.sleep(3) res = ask_way(person_list) print('%s問的結果是: %res' %(person,res)) return res res = ask_way(person_list) print(res)
運行結果以下:
C:\Python35\python3.exe G:/python_s3/day15/全局變量與局部變量.py ------------------------------------------------------------ hi 美男[zhurui],敢問路在何方 zhurui回答道:我不知道,但你慧眼識珠,我去幫你問問['caiyunjie', 'yuanhao', 'simon', 'william', 'zcz']... ------------------------------------------------------------ hi 美男[caiyunjie],敢問路在何方 caiyunjie回答道:我不知道,但你慧眼識珠,我去幫你問問['yuanhao', 'simon', 'william', 'zcz']... ------------------------------------------------------------ hi 美男[yuanhao],敢問路在何方 yuanhao回答道:我不知道,但你慧眼識珠,我去幫你問問['simon', 'william', 'zcz']... ------------------------------------------------------------ yuanhao問的結果是: 'simon說:我知道,東方財富網就在東方財富大廈A座,下肇嘉浜路地鐵站就是'es caiyunjie問的結果是: 'simon說:我知道,東方財富網就在東方財富大廈A座,下肇嘉浜路地鐵站就是'es zhurui問的結果是: 'simon說:我知道,東方財富網就在東方財富大廈A座,下肇嘉浜路地鐵站就是'es simon說:我知道,東方財富網就在東方財富大廈A座,下肇嘉浜路地鐵站就是 Process finished with exit code 0
遞歸特性:
1.必須有一個明確的結束條件
2.每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減小
3.遞歸效率不高,遞歸層次過多會致使棧溢出(在計算機中,函數調用是經過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層幀。因爲棧的大小不是無限的,因此,遞歸調用的次數過多,會致使棧溢出)
示例代碼以下:
#一、做用域即範圍
- 全局範圍(內置名稱空間與全局名稱空間屬於該範圍):全局存活,全局有效
- 局部範圍(局部名稱空間屬於該範圍):臨時存活,局部有效 #二、做用域關係是在函數定義階段就已經固定的,與函數的調用位置無關,以下 x = 1 def f1(): def f2(): print(x) return f2 x = 100 def f3(func): x=2 func() x = 10000 f3(f1()) 結果: C:\Python35\python3.exe G:/python_s3/day16/做用域.py 10000 #三、查看做用域:globals(),locals() LEGB 表明名字查找順序: locals -> enclosing function -> globals -> __builtins__ locals 是函數內的名字空間,包括局部變量和形參 enclosing 外部嵌套函數的名字空間(閉包中常見) globals 全局變量,函數定義所在模塊的名字空間 builtins 內置模塊的名字空間
代碼以下:
#一、 代碼方式一
def calc(x):
return x+1 res = calc(10) print(res) 輸出結果爲: C:\Python35\python3.exe G:/python_s3/day16/匿名函數.py 11 #二、用lambda方式表達 print (lambda x:x+1) #表明單純的輸出內存地址 func=lambda x:x+1 print (func(10)) 輸出結果爲: <function <lambda> at 0x00000000006EE0D0> 11
#表達方式1
name = 'simon'
def change_name(x):
return name+'_sb' res = change_name(name) print(res) #lambda方式表達: name='simon' func = lambda x:x+'_sb' print(func(name)) 輸出結果: C:\Python35\python3.exe G:/python_s3/day16/匿名函數.py simon_sb simon_sb
匿名函數補充:
f = lambda x,y,z:(x+1,y+1,z+1)
print(f(1,2,3)) 輸出結果爲: C:\Python35\python3.exe G:/python_s3/day16/匿名函數.py (2, 3, 4)
11 高階函數
知足倆個特性任意一個即爲高階函數
一、函數的傳入參數是一個函數名
二、函數的返回值是一個函數名
例一:不可變:不用變量保存狀態,不修改變量
#非函數式 a = 1 def incr_test1(): global a a+=1 return a incr_test1() print(a) 輸出結果: C:\Python35\python3.exe G:/python_s3/day16/匿名函數.py 2 #函數式 n=1 def incr_test2(n): return n+1 print(incr_test2(2)) print (n) 輸出結果: C:\Python35\python3.exe G:/python_s3/day16/匿名函數.py 3 1
簡單小結:
#空,None,0的布爾值爲False,其他都爲True
print(bool(''))
print(bool(None)) print(bool(0)) C:\Python35\python3.exe G:/python_s3/day16/內置函數.py False False False #bytes()函數,轉換成二進制 name='你好' print(bytes(name,encoding='utf-8')) print(bytes(name,encoding='utf-8').decode('utf-8')) #decode是將前面處理的編碼再解碼,還原成原來 print(bytes(name,encoding='gbk')) print(bytes(name,encoding='gbk').decode('gbk')) print(bytes(name,encoding='ascii')) #ascii不能編碼中文 C:\Python35\python3.exe G:/python_s3/day16/內置函數.py b'\xe4\xbd\xa0\xe5\xa5\xbd' 你好 b'\xc4\xe3\xba\xc3' 你好
max函數小結:
1、max函數處理的是可迭代對象,至關於一個for循環取出每一個元素進行比較,注意,不一樣類型之間不能進行比較
二、每一個元素間進行比較,是從每一個元素的第一個位置依次比較,若是這一個位置分出大小,後面的都不須要比較了,直接得出這倆元素的大小
#空,None,0的布爾值爲False,其他都爲True
# print(bool(''))
# print(bool(None))
# print(bool(0))
# #bytes()函數,轉換成二進制
# name='你好'
# print(bytes(name,encoding='utf-8'))
# print(bytes(name,encoding='utf-8').decode('utf-8')) #decode是將前面處理的編碼再解碼,還原成原來
# print(bytes(name,encoding='gbk'))
# print(bytes(name,encoding='gbk').decode('gbk'))
#
# print(bytes(name,encoding='ascii')) #ascii不能編碼中文
#chr()函數
# print(chr(97))
# print(dir(dict))
# print(divmod(10,36))
# dic ={'name':'alex'}
# print(dic)
# #可hash的數據類型即不可變類型,不可hash的類型便可變數據類型
# name='simon'
# print(hash(name))
# print(help(all))
#
# print(bin(10)) #10進制->2進制
# print(hex(12))
# print(oct(12)) #10進制轉8進制
#
# print(isinstance(1,int))
# l=[1,3,100,-1,-2,4]
# print(max(l))
# print(min(l))
#zip()函數,至關於拉鍊的做用
# print(list(zip(('a','b','c'),(1,2,3))))
# print(list(zip(('a','b','c'),(1,2,3))))
# print(list(zip(('a','b','c','d'),(1,2,3))))
#
# p={'name':'alex','age':18,'gender':'none'}
# print(list(zip(p.keys(),p.values()))) #不加list,只會輸出內存地址
# # print(list(p.keys()))
# # print(list(p.values()))
#
# print(list(zip('hello','12345'))) #zip方法裏傳兩個參數,都是序列類型(列表,元祖,字符串)
# l=[1,3,100,-1,-2,4]
# print(max(l))
# print(min(l))
people=[ {'name':'alex','age':1000}, {'name':'wupeiqi','age':10000}, {'name':'yuanhao','age':9000}, {'name':'simon','age':18}, ] print('-------->',max(people,key=lambda dic:dic['age'])) # age_dic={'age1':18,'age4':20,'age3':100,'age2':30} # print(max(age_dic.values())) # print((max(age_dic.keys()),max(age_dic.values()))) age_dic={'alex_age':18,'wupeiqi_age':20,'zsc_age':100,'lhf_age':30} # print(max(age_dic.values())) #默認比較的是字典的key # print(max(age_dic)) # for item in zip(age_dic.values(),age_dic.keys()): #(18.'alex_age') (20,'wupeiqi_age') # print(item) # print(list(max(zip(age_dic.values(),age_dic.keys())))) # # l = [ # (5,'e'), # (1,'b'), # (3,'a'), # (4,'d'), # ] # print(list(max(l))) # # l1=['a10','b12','c10',100] #不一樣類型之間不能進行比較 # l1=['a10','b12','c10'] #不一樣類型之間不能進行比較 # print(list(max(l))) # print(max(l1)) #總結 #一、max的比較,傳入的類型爲可迭代類型 #二、max的比較,從第一個位置開始比較,若是已經比較出大小,不會再比較後面的位置,直接輸出結果 # print(chr(97)) # print(ord('a')) #pow()函數: print(pow(2,3)) #2**3 print(pow(3,3,2)) #3**3/2 #reversed()函數,使結果反轉 # l=[1,2,3,4] # print(list(reversed(l))) # # #round()函數:四舍不入函數 # print(round(3.5)) # # #set()函數: # print(set('hello')) #selict()函數:切片 # l='hello' # # print(l[3:5]) # s1=slice(3,5) # s2=slice(1,4,2) # print(l[s1]) # print(l[s2]) # print(s2.start) # print(s2.stop) # print(s2.step) #sorted()函數: # l=[3,2,1,5,7] # l1=[3,2,'a',1,5,7] # print(sorted(l)) # print(sorted(l1)) #程序本質就是在比較大小,不一樣類型之間不能夠比較大小 people=[ {'name':'alex','age':1000}, {'name':'wupeiqi','age':10000}, {'name':'yuanhao','age':9000}, {'name':'simon','age':18}, ] print(sorted(people,key=lambda dic:dic['age'])) name_dic={ 'abyuanhao':900, 'alex':200, 'wupei':300, } print(sorted(name_dic)) print(sorted(name_dic,key=lambda key:name_dic[key])) print(sorted(zip(name_dic.values(),name_dic.keys()))) #str()函數 print(str('l')) print(str({'a':1})) #sum()函數 l=[1,2,3,4] print(sum(l)) print(sum(range(5))) p=range(10) print(sum(p)) #type()函數 l=[1,2,3,4] print('>>>>>>>',type(l)) msg='123' if type(msg) is str: msg=int(msg) msg+=1 print(msg) #var()函數 def test(): msg='人麼容量爲進入高溫熱未來惹我竟然我給我' # print(locals()) print(vars()) test() #import ----->sys-------->__import__() #__import__()函數: #能夠導入字符串 # import 'test' #不能導入字符串