1 什麼是函數? 2 爲何要用函數? 3 函數的分類:內置函數與自定義函數 4 如何自定義函數 語法 定義有參數函數,及有參函數的應用場景 定義無參數函數,及無參函數的應用場景 定義空函數,及空函數的應用場景 5 調用函數 如何調用函數 函數的返回值 函數參數的應用:形參和實參,位置參數,關鍵字參數,默認參數,*args,**kwargs 6 高階函數(函數對象) 7 函數嵌套 8 做用域與名稱空間 9 裝飾器 10 迭代器與生成器及協程函數 11 三元運算,列表解析、生成器表達式 12 函數的遞歸調用 13 內置函數 14 面向過程編程與函數式編程
1. 爲什麼要用函數之不用函數的問題html
#一、代碼的組織結構不清晰,可讀性差 #二、遇到重複的功能只能重複編寫實現代碼,代碼冗餘 #三、功能須要擴展時,須要找出全部實現該功能的地方修改之,沒法統一管理且維護難度極大
2. 函數是什麼python
針對二中的問題,想象生活中的例子,修理工須要實現準備好工具箱裏面放好錘子,扳手,鉗子等工具,而後遇到錘釘子的場景,拿來錘子用就能夠,而無需臨時再製造一把錘子。 修理工===>程序員 具有某一功能的工具===>函數 要想使用工具,須要事先準備好,而後拿來就用且能夠重複使用 要想用函數,須要先定義,再使用
3. 函數分類git
#一、內置函數 爲了方便咱們的開發,針對一些簡單的功能,python解釋器已經爲咱們定義好了的函數即內置函數。對於內置函數,咱們能夠拿來就用而無需事先定義,如len(),sum(),max() ps:咱們將會在最後詳細介紹經常使用的內置函數。 #二、自定義函數 很明顯內置函數所能提供的功能是有限的,這就須要咱們本身根據需求,事先定製好咱們本身的函數來實現某種功能,之後,在遇到應用場景時,調用自定義的函數便可。例如
一 如何自定義函數?程序員
#語法 def 函數名(參數1,參數2,參數3,...): '''註釋''' 函數體 return 返回的值 #函數名要能反映其意義
def auth(user:str,password:str)->int: ''' auth function :param user: 用戶名 :param password: 密碼 :return: 認證結果 ''' if user == 'egon' and password == '123': return 1 # print(auth.__annotations__) #{'user': <class 'str'>, 'password': <class 'str'>, 'return': <class 'int'>} user=input('用戶名>>: ').strip() pwd=input('密碼>>: ').strip() res=auth(user,pwd) print(res)
二 函數使用的原則:先定義,再調用編程
函數即「變量」,「變量」必須先定義後引用。未定義而直接引用函數,就至關於在引用一個不存在的變量名 #測試一 def foo(): print('from foo') bar() foo() #報錯 #測試二 def bar(): print('from bar') def foo(): print('from foo') bar() foo() #正常 #測試三 def foo(): print('from foo') bar() def bar(): print('from bar') foo() #會報錯嗎? #結論:函數的使用,必須遵循原則:先定義,後調用 #咱們在使用函數時,必定要明確地區分定義階段和調用階段 #定義階段 def foo(): print('from foo') bar() def bar(): print('from bar') #調用階段 foo()
三 函數在定義階段都幹了哪些事?app
#只檢測語法,不執行代碼 也就說,語法錯誤在函數定義階段就會檢測出來,而代碼的邏輯錯誤只有在執行時纔會知道
四 定義函數的三種形式ide
#一、無參:應用場景僅僅只是執行一些操做,好比與用戶交互,打印 #二、有參:須要根據外部傳進來的參數,才能執行相應的邏輯,好比統計長度,求最大值最小值 #三、空函數:設計代碼結構
#定義階段 def tell_tag(tag,n): #有參數 print(tag*n) def tell_msg(): #無參數 print('hello world') #調用階段 tell_tag('*',12) tell_msg() tell_tag('*',12) ''' ************ hello world ************ ''' #結論: #一、定義時無參,意味着調用時也無需傳入參數 #二、定義時有參,意味着調用時則必須傳入參數
def auth(user,password): ''' auth function :param user: 用戶名 :param password: 密碼 :return: 認證結果 ''' pass def get(filename): ''' :param filename: :return: ''' pass def put(filename): ''' :param filename: :return: ''' def ls(dirname): ''' :param dirname: :return: ''' pass #程序的體系結構立見
一 調用函數函數式編程
函數的調用:函數名加括號 1 先找到名字 2 根據名字調用代碼
二 函數返回值函數
無return->None return 1個值->返回1個值 return 逗號分隔多個值->元組
何時該有返回值? 調用函數,通過一系列的操做,最後要拿到一個明確的結果,則必需要有返回值 一般有參函數須要有返回值,輸入參數,通過計算,獲得一個最終的結果 何時不須要有返回值? 調用函數,僅僅只是執行一系列的操做,最後不須要獲得什麼結果,則無需有返回值 一般無參函數不須要有返回值
三 函數調用的三種形式工具
1 語句形式:foo() 2 表達式形式:3*len('hello') 3 當中另一個函數的參數:range(len('hello'))
一 形參與實參
#形參即變量名,實參即變量值,函數調用時,將值綁定到變量名上,函數調用結束,解除綁定
二 具體應用
#一、位置參數:按照從左到右的順序定義的參數 位置形參:必選參數 位置實參:按照位置給形參傳值 #二、關鍵字參數:按照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) def foo(x,y,*args): print(x,y) print(args) foo(1,2,*[3,4,5]) def foo(x,y,z): print(x,y,z) foo(*[1,2,3]) ===========**kwargs=========== def foo(x,y,**kwargs): print(x,y) print(kwargs) foo(1,y=2,a=1,b=2,c=3) def foo(x,y,**kwargs): print(x,y) print(kwargs) foo(1,y=2,**{'a':1,'b':2,'c':3}) def foo(x,y,z): print(x,y,z) foo(**{'z':1,'x':2,'y':3}) ===========*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}
一、寫函數,,用戶傳入修改的文件名,與要修改的內容,執行函數,完成批了修改操做
二、寫函數,計算傳入字符串中【數字】、【字母】、【空格] 以及 【其餘】的個數
三、寫函數,判斷用戶傳入的對象(字符串、列表、元組)長度是否大於5。
四、寫函數,檢查傳入列表的長度,若是大於2,那麼僅保留前兩個長度的內容,並將新內容返回給調用者。
五、寫函數,檢查獲取傳入列表或元組對象的全部奇數位索引對應的元素,並將其做爲新列表返回給調用者。
六、寫函數,檢查字典的每個value的長度,若是大於2,那麼僅保留前兩個長度的內容,並將新內容返回給調用者。
dic = {"k1": "v1v1", "k2": [11,22,33,44]}
PS:字典中的value只能是字符串或列表
#題目一 def modify_file(filename,old,new): import os with open(filename,'r',encoding='utf-8') as read_f,\ open('.bak.swap','w',encoding='utf-8') as write_f: for line in read_f: if old in line: line=line.replace(old,new) write_f.write(line) os.remove(filename) os.rename('.bak.swap',filename) modify_file('/Users/jieli/PycharmProjects/爬蟲/a.txt','alex','SB') #題目二 def check_str(msg): res={ 'num':0, 'string':0, 'space':0, 'other':0, } for s in msg: if s.isdigit(): res['num']+=1 elif s.isalpha(): res['string']+=1 elif s.isspace(): res['space']+=1 else: res['other']+=1 return res res=check_str('hello name:aSB passowrd:alex3714') print(res) #題目三:略 #題目四 def func1(seq): if len(seq) > 2: seq=seq[0:2] return seq print(func1([1,2,3,4])) #題目五 def func2(seq): return seq[::2] print(func2([1,2,3,4,5,6,7])) #題目六 def func3(dic): d={} for k,v in dic.items(): if len(v) > 2: d[k]=v[0:2] return d print(func3({'k1':'abcdef','k2':[1,2,3,4],'k3':('a','b','c')}))
一。裝飾器的造成過程:
如今我有一個需求,我想讓你測試這個函數的執行時間,在不改變這個函數代碼的狀況下:
1 import time 2 3 def func1(): 4 print('in func1') 5 6 def timer(func): 7 def inner(): 8 start = time.time() 9 func() 10 print(time.time() - start) 11 return inner 12 13 func1 = timer(func1) 14 func1()
可是若是有多個函數,我都想讓你測試他們的執行時間,你每次是否是都得func1 = timer(func1)?這樣仍是有點麻煩,由於這些函數的函數名多是不相同,有func1,func2,graph,等等,因此更簡單的方法,python給你提供了,那就是語法糖。
1 import time 2 def timer(func): 3 def inner(): 4 start = time.time() 5 func() 6 print(time.time() - start) 7 return inner 8 9 @timer #==> func1 = timer(func1) 10 def func1(): 11 print('in func1') 12 13 14 func1() 15 16 裝飾器---語法糖
剛剛咱們討論的裝飾器都是裝飾不帶參數的函數,如今要裝飾一個帶參數的函數
1 def timer(func): 2 def inner(a): 3 start = time.time() 4 func(a) 5 print(time.time() - start) 6 return inner 7 8 @timer 9 def func1(a): 10 print(a) 11 12 func1(1) 13 14 裝飾器——帶參數的裝飾器 15 16 裝飾器---帶參數的裝飾器
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func1 = timer(func1) def func1(a,b): print('in func1') @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func1('aaaaaa','bbbbbb') print(func2('aaaaaa')) 裝飾器---hold住全部參數的裝飾器
二。上面的裝飾器已經很是完美了,可是有咱們正常狀況下查看函數信息的方法在此處都會失效(問題/解決辦法)
def index(): '''這是一個主頁信息''' print('from index') print(index.__doc__) #查看函數註釋的方法 print(index.__name__) #查看函數名的方法 解決辦法: from functools import wraps def deco(func): @wraps(func) #加在最內層函數正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__) print(index.__name__)
三。裝飾器的主要功能和固定結構
裝飾器的結構 def timer(func): def inner(*args,**kwargs): '''執行函數以前要作的''' re = func(*args,**kwargs) '''執行函數以後要作的''' return re return inner 複製代碼
from functools import wraps def deco(func): @wraps(func) #加在最內層函數正上方 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper 裝飾器的固定格式--wraps版