深入淺出了解python函數(shù)

為了提高編寫的效率以及代碼的重用,所以把具有獨立功能的代碼塊組織為一個小模塊,這就是函數(shù)

一、定義函數(shù)

~~~

def 函數(shù)名():

? ? 代碼

Demo(一個打印‘hello word的使用’):

def function():

? ? print("hello word")

~~~

二、調(diào)用

函數(shù)名()

Demo:

?function()

注:我們python是一個非編譯語言,我們在調(diào)用函數(shù)時要在函數(shù)的定義下邊,否則會報錯

在使用過程中調(diào)用函數(shù)名加上一個小括號就可以了,如果不加()那么是一個函數(shù)的引用,不能夠成功調(diào)用

三、函數(shù)的分類

函數(shù)根據(jù)有沒有參數(shù),有沒有返回值,可以相互組合,一共有4種

無參數(shù),無返回值

此類函數(shù),不能接收參數(shù),也沒有返回值,一般情況下,打印提示燈類似的功能,使用這類的函數(shù)

無參數(shù),有返回值

此類函數(shù),不能接收參數(shù),但是可以返回某個數(shù)據(jù),一般情況下,像采集數(shù)據(jù),用此類函數(shù)

有參數(shù),無返回值

此類函數(shù),能接收參數(shù),但不可以返回數(shù)據(jù),一般情況下,對某些變量設(shè)置數(shù)據(jù)而不需結(jié)果時,用此類函數(shù)

有參數(shù),有返回值

此類函數(shù),不僅能接收參數(shù),還可以返回某個數(shù)據(jù),一般情況下,像數(shù)據(jù)處理并需要結(jié)果的應(yīng)用,用此類函數(shù)

四、文檔說明

def demo(a,b):

? ? "用來計算2個數(shù)的和"

? ? return a+b

可以執(zhí)行

help(demo)

查看函數(shù)的相關(guān)說明,一般情況函數(shù)的文檔說明包含:參數(shù)說明、函數(shù)作用、返回值三部分

五、變量

1)局部變量

局部變量,就是在函數(shù)內(nèi)部定義的變量

其作用范圍是這個函數(shù)內(nèi)部,即只能在這個函數(shù)中使用,在函數(shù)的外部是不能使用的

因為其作用范圍只是在自己的函數(shù)內(nèi)部,所以不同的函數(shù)可以定義相同名字的局部變量(打個比方,把你、我是當(dāng)做成函數(shù),把局部變量理解為每個人手里的手機(jī),你可有個iPhone8,我當(dāng)然也可以有個iPhone8了, 互不相關(guān))

局部變量的作用,為了臨時保存數(shù)據(jù)需要在函數(shù)中定義變量來進(jìn)行存儲

當(dāng)函數(shù)調(diào)用時,局部變量被創(chuàng)建,當(dāng)函數(shù)調(diào)用完成后這個變量就不能夠使用了

比如在講到for循環(huán)的時候

for i in range(10):

print(i)

i 就是相當(dāng)于局部變量 在其他位置不能使用只能在for循環(huán)中使用。

在函數(shù)中局部變量就是在函數(shù)中定義的變量

?2)全局變量

如果一個變量,既能在一個函數(shù)中使用,也能在其他的函數(shù)中使用,這樣的變量就是全局變量

打個比方:有2個兄弟 各自都有手機(jī),各自有自己的小秘密在手機(jī)里,不讓另外一方使用(可以理解為局部變量);但是家里的電話是2個兄弟都可以隨便使用的(可以理解為全局變量)

全局變量可以說在函數(shù)外面定義的變量,所有函數(shù)都可以使用到

demo:

# 定義全局變量

a =100

deftest1():

????print(a)# 雖然沒有定義變量a但是依然可以獲取其數(shù)據(jù)

deftest2():

????print(a)# 雖然沒有定義變量a但是依然可以獲取其數(shù)據(jù)

# 調(diào)用函數(shù)

test1()

test2()

全局變量能夠在所有的函數(shù)中進(jìn)行訪問

全局變量和局部變量名字相同

demo:

a = 100 #定義全局變量

def func():

????a = 10 # 定義局部變量,和全局變量名相同

? ? print(a) #函數(shù)內(nèi)在輸出時是局部的10,而不是100

print(a) #函數(shù)外面輸出100 局部變量在函數(shù)外面無法訪問

局部變量會覆蓋全局變量,在局部變量所在的塊或者函數(shù)內(nèi),對變量的操作不影響全局變量的值,全局變量不起作用,在局部變量所在的代碼塊或函數(shù)外部,全局變量才起作用。

這就是變量作用域的問題。

如果我們想在函數(shù)中修改全局變量而不是局部變量,那么我們需要使用global進(jìn)行聲明

a = 100 #定義全局變量

def func():

????global a # 聲明使用全局變量

????a = 10

? ? print(a) #在輸出時是局部的10

print(a) # 輸出10?global 聲明后將全部變量進(jìn)行修改

六、參數(shù)

為了讓一個函數(shù)更通用,即想讓它計算哪兩個數(shù)的和,就讓它計算哪兩個數(shù)的和,在定義函數(shù)的時候可以讓函數(shù)接收數(shù)據(jù),就解決了這個問題,這就是 函數(shù)的參數(shù)(接收到的參數(shù)就可以當(dāng)做局部變量來使用,python中沒有指針,參數(shù)的傳遞有兩種方式:值傳遞、引用傳遞。一般我們用的是引用傳遞)

參數(shù)在這里有分為形參和實參。我們可以理解形參就是函數(shù)上面定義時接收的變量名,實參就是調(diào)用的時候傳遞的參數(shù)。一般我們講到的參數(shù)就是指的形參,即函數(shù)定義時的參數(shù)。

1)形參

demo:

#定義一個函數(shù)作用是進(jìn)行兩個數(shù)進(jìn)行相加,在這里a,b就是參數(shù)

def add2num(a,b):

? ? c = a +b

? ? pring(c)

add2num(10,20) #調(diào)用函數(shù)計算兩個數(shù)的和

我們的python解析器首先去定義函數(shù)add2num,然后在進(jìn)行時調(diào)用函數(shù),調(diào)用時傳遞兩個參數(shù),分別給a,b

然后程序會走到c = a + b進(jìn)行計算,最后打印結(jié)果。

*? 缺省參數(shù)(在形參中默認(rèn)有值的參數(shù),稱之為缺省參數(shù))

調(diào)用函數(shù)時,缺省參數(shù)的值如果沒有傳入,則取默認(rèn)值。

demo:

下例會打印默認(rèn)的age,如果age沒有被傳入:

def printinfo(name, age=35):

????# 打印任何傳入的字符串

????print("name: %s"% name)??

?????print("age %d"% age)

# 調(diào)用printinfo函數(shù)

printinfo(name="miki")

# 在函數(shù)執(zhí)行過程中 age去默認(rèn)值35

printinfo(age=9,name="miki")

以上實例輸出結(jié)果:

name: miki

age:35

name: miki

age:9

注意:帶有默認(rèn)值的參數(shù)一定要位于參數(shù)列表的最后面

?* 不定長參數(shù)(有時可能需要一個函數(shù)能處理比當(dāng)初聲明時更多的參數(shù), 這些參數(shù)叫做不定長參數(shù),聲明時不會命名。)

def functionname([formal_args,] *args, **kwargs):

????"""函數(shù)_文檔字符串"""

????function_suite

????return[expression]

加了星號(*)的變量args會存放所有未命名的變量參數(shù),args為元組

而加**的變量kwargs會存放命名參數(shù),即形如key=value的參數(shù), kwargs為字典.

deffun(a, b, *args, **kwargs):

?"""可變參數(shù)演示示例"""

? ? ?print("a =%d"% a)

? ? ?print("b =%d"% b)

? ? ?print("args:")

? ? ?print(args)

? ? ?print("kwargs: ")

? ? ?forkey, valueinkwargs.items():

? ? ?????print("key=%s"% value)

?fun(1,2,3,4,5, m=6, n=7, p=8)# 注意傳遞的參數(shù)對應(yīng)

以上打印結(jié)果:

a =1

b =2

args:(3,4,5)

kwargs:?

p =8

m =6

n =7

第二次傳遞參數(shù):

?c = (3,4,5)

?d = {"m":6,"n":7,"p":8}

?fun(1,2, *c, **d)# 注意元組與字典的傳參方式

打印結(jié)果

a =1

b =2

args:(3,4,5)

kwargs:

?p =8

m =6

n =7

第三次調(diào)用

fun(1,2, c, d)# 注意不加星號與上面的區(qū)別

打印結(jié)果:

a =1

b =2

args:

((3,4,5), {'p':8,'m':6,'n':7})

kwargs:

注:如果很多個值都是不定長參數(shù),那么這種情況下,可以將缺省參數(shù)放到 *args的后面, 但如果有**kwargs的話,**kwargs必須是最后的

2)實參

?實參就是函數(shù)在調(diào)用時小括號里面寫入的參數(shù),實參可以傳遞一個值,也可以是一個引用。在后面的學(xué)習(xí)里形參還可以傳遞一個對象,或者是一個函數(shù)。因為他們都是一個引用,可以當(dāng)做一個參數(shù)來傳遞。

注意在使用中傳遞的參數(shù)實參數(shù)據(jù)類型要和接收方形參的數(shù)據(jù)類型一致。

七、返回值

所謂“返回值”,就是程序中函數(shù)完成一件事情后,最后給調(diào)用者的結(jié)果

想要在函數(shù)中把結(jié)果返回給調(diào)用者,需要在函數(shù)中使用return

如下示例:

def add2num(a, b):

????c = a+b

????return c

在返回后的數(shù)據(jù)一般情況我的會使用或者保存的這個值,那么我們可以用一個變量名去接收

#調(diào)用函數(shù),順便保存函數(shù)的返回值

result = add2num(100,98)

print(result)

1)返回多個值

有的函數(shù)返回的結(jié)果不僅僅只有一個,那么我們應(yīng)該怎么做呢?

defdivid(a, b):

? ??shang = a//b

? ???yushu = a%b

? ??return shang, yushu#默認(rèn)是元組

result = divid(5,2)

print(result)# 輸出(2, 1)

返回的值是一個元組,我們可以進(jìn)行拆包

a,b =??divid(5,2)

print(a) #打印結(jié)果為2

print(b) #打印結(jié)果為1

注:返回的數(shù)值一定要一一對應(yīng)才可以正常拆包

return后面可以是元組,列表、字典等,只要是能夠存儲多個數(shù)據(jù)的類型,就可以一次性返回多個數(shù)據(jù)

deffunction():

? ??# return [1, 2, 3]

? ??# return (1, 2, 3)

? ??return{"num1":1,"num2":2,"num3":3}

2)多個return

defcreate_nums():

? ??print("---1---")

? ??return1# 函數(shù)中下面的代碼不會被執(zhí)行,因為return除了能夠?qū)?shù)據(jù)返回之外,還有一個隱藏的功能:結(jié)束函數(shù)

? ??print("---2---")

? ??return2

? ??print("---3---")

一個函數(shù)中可以有多個return語句,但是只要有一個return語句被執(zhí)行到,那么這個函數(shù)就會結(jié)束了,因此后面的return沒有什么用處。

def create_nums(num):

? ??print("---1---")

? ??if num ==100:?

?? ??????print("---2---")

? ??????return?num+1# 函數(shù)中下面的代碼不會被執(zhí)行,因為return除了能夠?qū)?shù)據(jù)返回之外,還有一個隱藏的功能:結(jié)束函數(shù)

? ??else:?

?? ??????print("---3---")

? ??????return num+2

?result1 = create_nums(100)?

?print(result1)# 打印101

result2 = create_nums(200)

?print(result2)# 打印202

八、匿名函數(shù)

用lambda關(guān)鍵詞能創(chuàng)建小型匿名函數(shù)。這種函數(shù)得名于省略了用def聲明函數(shù)的標(biāo)準(zhǔn)步驟。

lambda函數(shù)的語法只包含一個語句,如下:

lambda[arg1 [,arg2,.....argn]]:expression

如下實例:

sum =lambda arg1, arg2: arg1 + arg2

#調(diào)用sum函數(shù)

print("Value of total : ", sum(10,20))

print("Value of total : ", sum(20,20))

以上實例輸出結(jié)果:

Value of total :30

Value of total :40

Lambda函數(shù)能接收任何數(shù)量的參數(shù)但只能返回一個表達(dá)式的值

匿名函數(shù)不能直接調(diào)用print,因為lambda需要一個表達(dá)式

lambda函數(shù)一般情況下會當(dāng)做一個參數(shù)來傳遞,比如做字典的排序?;蛘叻诺礁呒壓瘮?shù)中使用,后面會有講到。

九、函數(shù)的嵌套調(diào)用

在一個函數(shù)中嵌套調(diào)用另外一個函數(shù),就是函數(shù)的嵌套調(diào)用。

deftestB():

? ??print('---- testB start----')?

? ???print('這里是testB函數(shù)執(zhí)行的代碼...(省略)...')?

? ???print('---- testB end----')

deftestA():

? ??print('---- testA start----')?

? ???testB()?

? ???print('---- testA end----')?

testA()

運行結(jié)果:

---- testA start----

? ? ---- testB start----

? ? 這里是testB函數(shù)執(zhí)行的代碼...(省略)...

? ? ---- testB end----

? ? ---- testA end----


如果函數(shù)A中,調(diào)用了另外一個函數(shù)B,那么先把函數(shù)B中的任務(wù)都執(zhí)行完畢之后才會回到上次 函數(shù)A執(zhí)行的位置

十、遞歸

如果一個函數(shù)在內(nèi)部不調(diào)用其它的函數(shù),而是自己本身的話,這個函數(shù)就是遞歸函數(shù)。

舉個例子,我們來計算階乘?n! = 1 * 2 * 3 * ... * n

def func(num):

? ? if num > 1:

? ? ? ? reault = num *?func(num-1)

? ? else:

? ? ? ? reault = 1

? ? return?reault

func(5)

調(diào)用流程


十一、閉包

閉包也具有提高代碼可復(fù)用性的作用。后邊講到的裝飾器就是用到閉包的原理

# 定義一個函數(shù)

def test(number):

# 在函數(shù)內(nèi)部再定義一個函數(shù),并且這個函數(shù)用到了外邊函數(shù)的變量,那么將這個函數(shù)以及用到的一些變量稱之為閉包

? ??def test_in(number_in):

? ??????print("in test_in 函數(shù), number_in is %d"% number_in)

? ??????return number+number_in #number_in其實是一個函數(shù)的引用,是把函數(shù)的引用當(dāng)做參數(shù)來傳遞

? ??# 其實這里返回的就是閉包的結(jié)果

? ??return test_in? #返回一定是內(nèi)部函數(shù)的引用,不能帶有小括號


# 給test函數(shù)賦值,這個20就是給參數(shù)

ret = test(20)? ? ? ? # 在這里執(zhí)行的是test函數(shù),然后將test_in函數(shù)的引用返回,重新賦值給ret

# 注意這里的100其實給參數(shù)

print(ret(100))? ?#在這里使用的ret(100)? 相當(dāng)于test_in(100)? 也就相當(dāng)于 test(20)(100) 最終返回的是 20+100

#注 意這里的200其實給參數(shù)

print(ret(200))???#在這里使用的ret(100)? 相當(dāng)于test_in(200)? 也就相當(dāng)于 test(20)(200) 最終返回的是 20+200

由于閉包引用了外部函數(shù)的局部變量,則外部函數(shù)的局部變量沒有及時釋放,消耗內(nèi)存

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 這篇筆記記錄的知識點:函數(shù)的基本概念自定義函數(shù)函數(shù)的幾種參數(shù) 編程的三種方式:1.OOP 面向?qū)ο缶幊蹋f物皆對象...
    古月半半閱讀 1,090評論 0 2
  • 第5章 函數(shù)和函數(shù)式編程 5.1 引言函數(shù)是組織好的,可重復(fù)使用的,用來實現(xiàn)單一,或相關(guān)聯(lián)功能的代碼段。函數(shù)...
    VIVAFT閱讀 1,090評論 0 5
  • """ 第八章 函數(shù) """ # 背景:問題 ,控制臺上打印每行5個星星,五行 # print("其他的代碼塊")...
    天刀笑劍鈍閱讀 549評論 0 0
  • 高階python 函數(shù)式編程 - 函數(shù)式 函數(shù)式編程(FunctionalProgramming) - 基于lam...
    July_whj閱讀 581評論 0 1
  • 叮叮叮,起床啦!按掉鬧鐘,翻了一個身,打開網(wǎng)易云音樂,民謠搖起來。 隨手配一張圖,放在朋友圈。早上好,我的朋友們!...
    貍貍貍666閱讀 987評論 1 5

友情鏈接更多精彩內(nèi)容