函數是python程序中的基本模塊化單位,它是一段可重用的代碼,可以被多次調用執行。函數接受一些輸入參數,并且在執行時可能會產生一些輸出結果。函數定義了一個功能的封裝,使得代碼能夠模塊化和組織結構化,更容易理解和維護。在python中,函數可以返回一個值或者不返回任何值,而且函數的參數可以是任何python對象,包括數字、字符串、列表、元組等。python內置了許多函數,同時也支持用戶自定義函數。
Python 中可以創建這樣四種類型的函數:
- 全局函數:定義在模塊
- 局部函數:嵌套于其它函數中
- lambda函數:表達式,如需多次調用
- 方法:與特定數據類型關聯的函數,并且只能與數據類型關聯一起使用
函數創建的相關定義規則:
- 函數代碼塊以def關鍵詞開頭,后接函數標識符名稱和圓括號()
- 任何傳入參數和自變量必須放在圓括號中間,圓括號之間可以用于定義參數
- 函數的第一行語句可以選擇性地使用文檔字符串,-用于存放函數說明
- 函數內容以冒號起始,并且必須保持縮進,否則會當作普通語句來執行
- return
[表達式]
結束函數,選擇性地返回一個值給調用方,也就是返回值
5.1 有參與無參函數
Python是一種支持函數編程的編程語言。在Python中,函數可以分為有參函數和無參函數。有參函數接受零個或多個參數,并執行操作或返回一個值。無參函數則根本不需要任何參數。通常,有參函數通過其參數來接受外部數據,以便在函數執行時進行操作或返回結果。而無參函數則只提供在函數代碼中預定義的代碼塊。因此,無論是有參函數還是無參函數,它們都是Python編程中非常重要的組成部分,具有廣泛的用途。
定義無參函數: 如下我們編寫一個無參數的函數,并在后面直接調用其執行.
>>> import sys
>>>
>>> def lyshark(): #定義lyshark()函數,函數執行打印
... print("hello lyshark!")
>>>
>>> lyshark() #調用了lyshark()函數,打印一段話
hello lyshark!
>>>
定義有參函數: 如下我們編寫兩個函數,分別給予相應的參數,其返回值則不相同.
>>> import sys
>>>
>>> def area(width,height): #一個計算面積的函數,其中width,height是形式參數
... return width * height
>>>
>>> def print_me(name): #一個打印函數,其中name是形式參數
... print("welcome:",name)
>>>
>>>
>>> print_me("lyshark") #調用打印函數,并摻入相應的數值
welcome: lyshark
>>>
>>> w=10
>>> h=25
>>> print(area(w,h)) #計算平方并打印,傳入數值變量計算
250
5.2 函數參數傳遞
默認情況下,參數通過其位置進行傳遞,從左至右,這意味著,必須精確地傳遞和函數頭部參數一樣多的參數,但也可以通過關鍵字參數、默認參數或參數容器等改變這種機制.
通常python中所支持的參數傳遞形式:
- 普通參數:普通參數傳遞,在定義函數時就指定了規律是從左至右傳遞
- 默認參數:定義函數時是使用
"name=value"
的語法直接給變量一個值,從而傳入的值可以少于參數個數 - 指定參數:調用函數時指定
"name形式參數=value實際參數"
的語法通過參數名進行匹配 - 動態參數:在我們定義函數時,形式參數中收集任意多基于普通參數
【定義函數時使用* :收集普通參數,返回元組,*args】【定義函數時使用**:收集指定參數,返回列表,**kwargs】
- 動態參數解包:在調用函數時,使用
**開頭
的參數,從而傳遞任意多基于普通或指定參數
關于函數中形式參數與實際參數的區別:
- 形式參數:形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元.因此,形參只在函數內部有效.函數調用結束返回主調用函數后則不能再使用該形參變量
- 實際參數:實參可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參.因此應預先用賦值,輸入等辦法使參數獲得確定值
普通參數傳遞: 定義一個函數體,并且為其傳遞三個參數,執行函數并打印結果.
>>> def stu(name,age,country):
... print("姓名:",name)
... print("年齡:",age)
... print("國籍:",country)>>> stu("lyshark",22,"CN")
姓名: lyshark
年齡: 22
國籍: CN
>>>
>>> stu("zhangsan",33,"CN")
姓名: zhangsan
年齡: 33
國籍: CN
帶默認參數傳遞: 同樣的,我們可以給指定的字段添加默認參數,如果用戶不輸入則默認使用指定參數,此處需要注意:如果您要使用帶默認參數的函數,則需要把帶參數的字段,放在函數最后一項.
>>> def stu(age,country,name="none",sex="man"):
... print("姓名: ",name)
... print("性別: ",sex)
... print("年齡: ",age)
... print("國籍: ",country)
...
>>>
>>> stu(23,"CN","lyshark","man") #此時我們給予全部的參數則無默認值
姓名: lyshark
性別: man
年齡: 23
國籍: CN
>>> stu("zhangsan","mal",23,"CN") #形參如何排列,實參就得如何排列
姓名: 23
性別: CN
年齡: zhangsan
國籍: mal
>>> stu(23,"CN") #傳遞輸入是忽略帶有默認值的字段
姓名: none
性別: man
年齡: 23
國籍: CN
動態參數傳遞(傳遞列表): 若你的函數在定義時不確定用戶想傳入多少個參數,就可以使用非固定參數,傳遞一個列表.
>>> def stu(name,age,*args): #*args會把多傳入的參數變成一個元組.
... print(name,age,args)
>>>
>>> stu("lyshark",22)
lyshark 22 () #這個()就是args,只是因為沒傳值,所以為空.
>>>
>>> stu("lyshark",22,"a","b","c","d") #傳值后會把它當作一個列表
lyshark 22 ('a', 'b', 'c', 'd')
>>>
>>> ls=[1,2,3,4,5] #先聲明列表
>>> stu("lyshark",22,ls) #傳遞這個列表
lyshark 22 ([1, 2, 3, 4, 5],) #第三個值,打印出列表
執行函數時有·*
,則把所有迭代對象拆分為單個元素作為元組的元素,如傳入列表,會把列表中每一個元素遍歷添加到元組中當作一個元素,如下可看到差別.
>>> def fun(*args): #動態參數返回元組
... print(args,type(args))
>>>
>>> lists=[1,2,3,4] #定義要傳遞的列表
>>> fun(lists) #傳遞一個列表
([1, 2, 3, 4],) <class 'tuple'>
>>>
>>> fun(*lists)
(1, 2, 3, 4) <class 'tuple'>
動態參數傳遞(傳遞字典): 我們可以使用**kwargs
默認參數,來接收一個字典,并通過函數體打印出來.
>>> def stu(name,age,*args,**kwargs):
... print(name,age,args,kwargs)
>>>
>>> stu("lyshark",22) #傳遞默認參數
lyshark 22 () {}
>>>
>>> stu("lyshark",22,"a","b",sex="Male",province="山東") #傳遞元組和字典
lyshark 22 ('a', 'b') {'sex': 'Male', 'province': '山東'}
如上方法是在調用函數的時候傳遞的字典,當然我們也可以直接將一個現有的字典傳遞進去.
>>> def fun(name,**kwargs):
... print(name,kwargs)
>>>
>>> dic={"k1":"v1","k2":"v2"}
>>>
>>> fun("lyshark",**dic)
lyshark {'k1': 'v1', 'k2': 'v2'}
動態參數傳遞(萬能參數): 我們使用*與**
通常情況下可以傳遞任何值,所以稱作萬能參數.
>>> def fun(*args,**kwargs):
... print(args,type(args))
... print(kwargs,type(kwargs))
>>>
>>> lists=[1,2,3,4,5,6,7,8,9]
>>> dic={"a":1001,"b":1002,"c":1003}
>>>
>>> fun(*lists,**dic)
(1, 2, 3, 4, 5, 6, 7, 8, 9) <class 'tuple'>
{'a': 1001, 'b': 1002, 'c': 1003} <class 'dict'>
拓展補充: 其實在python中我們經常看到萬能參數,比如str.format()
方法,就是一個典型的萬能參數的例子,如下演示,了解即可.
>>> string="hello {0},age {1}"
>>> print(string.format("lyshark",22))
hello lyshark,age 22
>>>
>>> string="hello {name},age {age}"
>>> print(string.format(name="lyshark",age=22))
hello lyshark,age 22
>>>
>>> string="hello {0},age {1}"
>>> print(string.format(*["lyshark",22]))
hello lyshark,age 22
>>>
>>> dic ={"name":"lyshark","age":22}
>>> string="hello {name},age {age}"
>>>
>>> print(string.format(**dic))
hello lyshark,age 22
在多個同名函數的情況下,默認使用最后后一個函數,最后一個函數名會指向新的內存對象,函數名是函數體在內存中的引用.
>>> def fun(a,b):
... return a+b
>>> def fun(a,b):
... return a*b
>>>
>>> print(fun(3,3))
9
函數傳遞的是指針,所以我們的數據會被保留下來如下例子.
>>> def fun(x):
... x.append(8888)
>>>
>>> lists=[1,2,3]
>>> fun(lists)
>>>
>>> print(lists)
[1, 2, 3, 8888]
如下例子由于函數沒有定義返回值,所以默認為none.
>>> def fun(x):
... x.append(8888)
>>>
>>> lists=[1,2,3]
>>> lists=fun(lists)
>>>
>>> print(lists)
None
5.3 通用函數返回值
return語句用來實現退出函數,選擇性地向調用方返回一個表達式,不帶參數值的return語句返回None,之前的例子都沒有示范如何返回數值,如下先來看一下返回語句的規則:
- Return 語句用于退出函數,選擇性地向調用方返回一個表達式
- 如果Return語句不帶任何參數,則不帶參數值的Return語句默認返回None
- 函數在執行過程中只要遇到Return,就會停止執行并返回結果,通俗的將遇到ret說明函數結束
默認函數返回: 如下使用默認函數返回,通常情況下返回一個確定數值.
>>> def add(num1,num2):
... sum=num1+num2
... print("函數內返回:",sum)
... sum=sum+100
... return sum
>>>
>>> temp=add(10,20)
函數內返回: 30
>>> print("函數外返回:",temp)
函數外返回: 130
選擇性返回: 在函數體內部使用判斷結構,如果輸入的是偶數返回0,否則返回-1.
>>> def check(num):
... if (num %2 ==0):
... return 0
... else:
... return -1
>>>
>>> print(check(2))
0
>>> print(check(3))
-1
返回一個列表: 通過函數體的運算后,將一個列表返回給外部來接收使用.
import osdef temp_max(*args):all_max=[]temp=argsfor x in range(len(*args)):if temp[0][x] >= 50:all_max.append(temp[0][x])return all_maxa=[11,56,87,99,86,34,56,22,77,53]
my_max=[]my_max=temp_max(a)
print(my_max)
5.4 通用函數閉包
函數是一段可執行代碼,編譯后就固化了,每個函數在內存中只有一份實例,得到函數的入口點便可以執行函數了,一個函數可作為另一個函數的參數或返回值,可以賦給一個變量.函數可以嵌套定義,即在一個函數內部可以定義另一個函數,有了嵌套函數這種結構,便會產生閉包問題.
閉包是由函數及其相關的引用環境組合而成的實體(閉包=函數+引用環境)這個從字面上很難理解,python中的閉包從表現形式上定義(解釋)為:如果在一個內部函數里,對在外部作用域(但不是在全局作用域)的變量進行引用,那么內部函數就被認為是閉包(closure).這個定義是相對直白的,好理解的,下面舉一個簡單的例子來說明.
>>> def adds(x):
... def adder(y):return x+y
... return adder
...
>>> c=adds(10)
>>> type(c)
<class 'function'>
>>> c.__name__
'adder'
>>> c(10)
20
如上代碼,在一個內部函數里:adder(y)就是這個內部函數,對在外部作用域(但不是在全局作用域)的變量進行引用:x就是被引用的變量,x在外部作用域adds里面,但不在全局作用域里,則這個內部函數adder就是一個閉包.閉包=函數塊+定義函數時的環境,adder就是函數塊,x就是環境,當然這個環境可以有很多,不止一個簡單的x.
閉包返回函數: 通過使用閉包,返回一個函數,并使用函數做進一步的計算.
import osdef post_sum(*args):def sum():x=0for y in args:x=x+yreturn xreturn sumpost_sum(1,2,3,4,5) #post_sum并沒執行,而是返回一個指向求和的函數的函數名sum的內存指針fp=post_sum(1,2,3,4,5)
print(type(fp)) #調用f()函數,才真正調用了sum函數進行求和,這其實就是閉包print(fp())
閉包選擇返回: 通過返回值判斷,來使用不同的閉包函數,從而返回不同的結果.
import osdef post(temp,*args):def sum():x=0for y in args:x=x+yreturn xdef div():x=1for y in args:x=x*yreturn xif temp=="1":return sumelse:return divfp=post("1",1,2,3,4) #使用加法閉包函數
print(type(fp))
print(fp())fp1=post("0",1,2,3,4) #使用乘法閉包函數
print(type(fp1))
print(fp1())
閉包返回函數列表: 通過使用閉包函數,一次性返回多個函數列表,每個函數擁有獨立空間.
>>> def count():fs=[]for i in range(1,4):def f():return i*ifs.append(f)return fs>>> f1,f2,f3=count()
>>> print(f1())
9
>>> print(f2())
9
>>> print(f3())
9
5.5 函數嵌套與遞歸
除了函數的閉包以外,函數還支持兩種調用方式,一種是嵌套函數,另一種是遞歸函數,這里需要注意的是,最好在開發中盡量少用這樣的結構,這種結構一旦層數變多將很難后期進行維護,所以你懂的.
- 嵌套函數:即指在一個函數體中,嵌套另外一個函數體,內部函數執行后將結果返回給外部函數使用
- 遞歸函數:函數在其內部調用它自己,就叫做遞歸,但遞歸需設置退出條件,不然會一直遞歸下去,變成一個死循環
嵌套函數: 定義一個嵌套函數,并打印出其執行軌跡,并理解其原理.
import osname="lyshark"def chage_name():name="lyshark blog"def chage_name_new():name="mkdirs blog"print("第3層循環打印: ",name)chage_name_new() #在函數內部調用內部的函數print("第2層循環打印: ",name) #第二層函數執行結果chage_name() #調用最外層函數
print("查看最外層變量: ",name) #查看外層變量>>>
第3層循環打印: mkdirs blog
第2層循環打印: lyshark blog
查看最外層變量: lyshark
遞歸函數: 使用遞歸的方式實現指定數字的階乘,如下所示.
import osdef fun(n):if 0==n: # n=0 的話直接返回空,對用戶輸入的零進行判斷return Noneelif 1==n: # n=1 的話就不再遞歸return nelse:return n*fun(n-1) # 遞歸在執行f(n-1),直到f(1)print(fun(5)) # 120
'''f(5)的執行過程如下===> f(5)===> 5 * f(4)===> 5 * (4 * f(3))===> 5 * (4 * (3 * f(2)))===> 5 * (4 * (3 * (2 * f(1))))===> 5 * (4 * (3 * (2 * 1)))===> 5 * (4 * (3 * 2))===> 5 * (4 * 6)===> 5 * 24===> 120
'''
5.6 LAMBDA匿名函數
Lambda是Python中的一個關鍵字,用于創建匿名函數。匿名函數是沒有名稱的小函數,通常用于僅需要一次性使用的場景。它們可以被傳遞為參數,或者作為返回值返回給其他函數使用。
Lambda函數的語法很簡單,使用lambda關鍵字定義,后跟參數,并且只能包含一個表達式。該表達式的結果則作為函數返回值。
關于匿名函數的一些注意事項:
- lambda只是一個表達式,函數體比 def 簡單很多
- lambda表達式會自動return返回值,條件為真返回True,條件為假返回False
- lambda函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間里的參數
- lambda的主體是一個表達式,而不是一個代碼塊,僅僅能在lambda表達式中封裝有限的邏輯進去
- lambda函數看起來只能寫一行,卻不等同于C或C++的內聯函數,應該區別對待,畢竟是兩們不同語言.
定義匿名函數: 使用功能最基本的語法定義一個匿名函數.
>>> sum=lambda x,y,z: x+y+z
>>>
>>> print("三個數相加:",sum(10,20,30))
三個數相加: 60
定義匿名函數: 對于簡單的函數,也存在一種簡便的表示方式,即:lambda表達式.
# ######################### 普通函數 #########################
# 定義函數(普通方式)
def func(arg):return arg + 1# 執行函數
result = func(123)# ######################### lambda ########################## 定義函數(lambda表達式)
my_lambda = lambda arg : arg + 1# 執行函數
result = my_lambda(123)
向匿名函數傳遞列表: 想一個匿名函數傳遞一個列表,并分別計算后返回相應數據.
>>> res=map(lambda x:x**2,[1,5,4,8])
>>>
>>> for i in res:print(i)1
25
16
64
本文作者: 王瑞
本文鏈接: https://www.lyshark.com/post/be3b076e.html
版權聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協議。轉載請注明出處!