- 一 引子
- 二 定義函數
- 三 調用函數
- 四 函數的參數
- 五 練習題
一 引子
1、 爲何要用函數之不用函數的問題
#1、代碼的組織結構不清晰,可讀性差
#2、遇到重複的功能只能重複編寫實現代碼,代碼冗餘
#3、功能需要擴展時,需要找出所有實現該功能的地方修改之,無法統一管理且維護難度極大
2、函數是什麼
生活中的例子,修理工需要實現準備好工具箱裏面放好錘子,扳手,鉗子等工具,然後遇到錘釘子的場景,拿來錘子用就可以,而無需臨時再製造一把錘子。
修理工===>程序員
具備某一功能的工具===>函數
要想使用工具,需要事先準備好,然後拿來就用且可以重複使用
要想用函數,需要先定義,再使用
3、函數分類
#1、內置函數
爲了方便我們的開發,針對一些簡單的功能,python解釋器已經爲我們定義好了的函數即內置函數。對於內置函數,我們可以拿來就用而無需事先定義,如len(),sum(),max()
#2、自定義函數
很明顯內置函數所能提供的功能是有限的,這就需要我們自己根據需求,事先定製好我們自己的函數來實現某種功能,以後,在遇到應用場景時,調用自定義的函數即可。
二 定義函數
1、如何自定義函數?
#語法
def 函數名(參數1,參數2,參數3,...):
'''註釋'''
函數體
return 返回的值
#函數名要能反映其意義
def auth(user:str,password:str)->int:
'''
auth function
:param user: 用戶名
:param password: 密碼
:return: 認證結果
'''
if user == 'hgz' 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)
2、函數使用的原則:先定義,再調用
函數即“變量”,“變量”必須先定義後引用。未定義而直接引用函數,就相當於在引用一個不存在的變量名
#測試一
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()
3、函數在定義階段都幹了哪些事?
#只檢測語法,不執行代碼
也就說,語法錯誤在函數定義階段就會檢測出來,而代碼的邏輯錯誤只有在執行時纔會知道
例如:
def foo():
aa
dd
dd
print('from foo')
#在執行該代碼的時候,並不會報錯,一旦點用就會報錯“NameError: name 'aa' is not defined“
4、定義函數的三種形式
#1、無參:應用場景僅僅只是執行一些操作,比如與用戶交互,打印
#2、有參:需要根據外部傳進來的參數,才能執行相應的邏輯,比如統計長度,求最大值最小值
#3、空函數:設計代碼結構
#定義階段
def tell_tag(tag,n): #有參數
print(tag*n)
def tell_msg(): #無參數
print('hello world')
#調用階段
tell_tag('*',12)
tell_msg()
tell_tag('*',12)
'''
************
hello world
************
'''
#結論:
#1、定義時無參,意味着調用時也無需傳入參數
#2、定義時有參,意味着調用時則必須傳入參數
def auth(user,password):
'''
auth function
:param user: 用戶名
:param password: 密碼
:return: 認證結果
'''
pass
def get(filename):
'''
:param filename:
:return:
'''
pass ## 見到pass,則get爲空函數,常在定義程序邏輯框架的時候使用
def put(filename):
'''
:param filename:
:return:
'''
def ls(dirname):
'''
:param dirname:
:return:
'''
pass
#程序的體系結構立見
三 調用函數
1、調用函數
函數的調用:函數名加括號
1 先找到名字
2 根據名字調用代碼
2、函數返回值
無return->None
return 1個值->返回1個值
return 逗號分隔多個值->元組
什麼時候該有返回值?
調用函數,經過一系列的操作,最後要拿到一個明確的結果,則必須要有返回值
通常有參函數需要有返回值,輸入參數,經過計算,得到一個最終的結果
什麼時候不需要有返回值?
調用函數,僅僅只是執行一系列的操作,最後不需要得到什麼結果,則無需有返回值
通常無參函數不需要有返回值
3、函數調用的三種形式
1 語句形式:foo()
2 表達式形式:3*len('hello')
3 當做另外一個函數的參數:range(len('hello'))
四、函數的參數
1、形參與實參
#形參即變量名,實參即變量值,函數調用時,將值綁定到變量名上,函數調用結束,解除綁定
例如:
def auth(user,password): ## user,password爲形參
'''
auth function
:param user: 用戶名
:param password: 密碼
:return: 認證結果
'''
pass
auth(hgz,123) ##函數auth傳入的“hgz,123”爲實參
2、具體應用
#1、位置參數:按照從左到右的順序定義的參數
位置形參:必選參數
位置實參:按照位置給形參傳值
#2、關鍵字參數:按照key=value的形式定義的實參
無需按照位置爲形參傳值
注意的問題:
1. 關鍵字實參必須在位置實參右面
2. 對同一個形參不能重複傳值
#3、默認參數:形參在定義時就已經爲其賦值
可以傳值也可以不傳值,經常需要變得參數定義成位置形參,變化較小的參數定義成默認參數(形參)
注意的問題:
1. 只在定義時賦值一次
2. 默認參數的定義應該在位置形參右面
3. 默認參數通常應該定義成不可變類型
#4、可變長參數:
可變長指的是實參值的個數不固定
而實參有按位置和按關鍵字兩種形式定義,針對這兩種形式的可變長,形參對應有兩種解決方案來完整地存放它們,分別是*args,**kwargs
===========*args=========== #接收位置實參,以tuple的形式存儲
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)
#5、命名關鍵字參數:*後定義的參數,必須被傳值(有默認值的除外),且必須按照關鍵字實參的形式傳遞
可以保證,傳入的參數中一定包含某些關鍵字
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、練習題
1、寫函數,,用戶傳入修改的文件名,與要修改的內容,執行函數,完成批了修改操作
2、寫函數,計算傳入字符串中【數字】、【字母】、【空格] 以及 【其他】的個數
3、寫函數,判斷用戶傳入的對象(字符串、列表、元組)長度是否大於5。
4、寫函數,檢查傳入列表的長度,如果大於2,那麼僅保留前兩個長度的內容,並將新內容返回給調用者。
5、寫函數,檢查獲取傳入列表或元組對象的所有奇數位索引對應的元素,並將其作爲新列表返回給調用者。
6、寫函數,檢查字典的每一個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','hgz','NB')
#題目二
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:hgz passowrd:123')
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')}))