最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python函數(shù)定義、參數(shù)、返回值與作用域示例詳解

 更新時(shí)間:2026年04月21日 10:32:09   作者:艾莉絲努力練劍  
函數(shù)是組織好的、可重復(fù)使用的代碼塊,用于執(zhí)行特定任務(wù),在Python中函數(shù)可以讓我們把復(fù)雜的程序分解成小的模塊,提高代碼的可讀性和復(fù)用性,這篇文章主要介紹了Python函數(shù)定義、參數(shù)、返回值與作用域的相關(guān)資料,需要的朋友可以參考下

1 ~> 什么是函數(shù)?

1.1 函數(shù)的概念

我們編程中的函數(shù)其實(shí)和數(shù)學(xué)中的函數(shù)有一定的相似之處:

數(shù)學(xué)上的函數(shù),比如y=sinx,x取不同的值,y就會(huì)得到不同的結(jié)果

編程中的函數(shù),指的是 一段可以被重復(fù)使用的代碼片段。

1.2 代碼示例

1.2.1 代碼示例:求數(shù)列的和,不使用函數(shù)

# 1. 求 1 - 100 的和
sum = 0
for i in range(1, 101):
    sum += i
print(sum)
# 2. 求 300 - 400 的和
sum = 0
for i in range(300, 401):
    sum += i
print(sum)
# 3. 求 1 - 1000 的和
sum = 0
for i in range(1, 1001):
    sum += i
print(sum)

我們通過觀察可以發(fā)現(xiàn),這幾組代碼基本是相似的,只有一點(diǎn)點(diǎn)差異,可以把重復(fù)代碼提取出來,寫成一個(gè)函數(shù)。

實(shí)際開發(fā)中,復(fù)制粘貼是一種不太好的策略,實(shí)際開發(fā)的重復(fù)代碼可能存在幾十份甚至上百份。
一旦這個(gè)重復(fù)代碼需要被修改,那就得改幾十次,非常不便于維護(hù)。

1.2.2 代碼示例:求數(shù)列的和,使用函數(shù)

# 定義函數(shù)
def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)
# 調(diào)用函數(shù)
sum(1, 100)
sum(300, 400)
sum(1, 1000)

這里我們可以明顯看到——重復(fù)的代碼已經(jīng)被消除了。

1.3 最佳實(shí)踐:針對(duì)上面的示例

# 函數(shù)
# 函數(shù)是什么
# 三角函數(shù) sin、cos
# “隱射關(guān)系”
# 函數(shù):一段可以被反復(fù)使用的代碼   ctrl + c,ctrl + v
# 1、復(fù)制代碼,必須要非常仔細(xì)地進(jìn)行細(xì)節(jié)調(diào)整,尤其是在數(shù)據(jù)不同的情況下
# 2、一旦復(fù)制過的代碼需要調(diào)整,復(fù)制了幾份就得調(diào)整幾次(搞不清楚這個(gè)代碼究竟被復(fù)制了幾份了)
# 因此,盡量還是不要復(fù)制代碼,盡量做好代碼“復(fù)用”
# 其他邏輯都是一樣的,我們可以用函數(shù)的方式,達(dá)到復(fù)用代碼的效果
# 1、求1 - 100的和
thSum = 0
for i in range(1,101):
    thSum += i
print(thSum)
# 2、求300 - 400的和
thSum = 0   # 由于前面已經(jīng)有了thSum了,這里相當(dāng)于賦值操作
for i in range(300,401):
    thSum += i
print(thSum)
#3、求1 - 1000的和
thSum = 0
for i in range(1,1001):
    thSum += i
print(thSum)
# 在新的文件里面實(shí)現(xiàn)這個(gè)函數(shù)

我們創(chuàng)建一個(gè)新的文件,并且在新的文件里面實(shí)現(xiàn)這個(gè)函數(shù)——

# 使用函數(shù)的方式來解決剛才的問題:
# 有什么地方要改也只要改一次就好了

# 定義一個(gè)求和函數(shù)
def calcSum(beg,end):
    theSum = 0
    for i in range(beg,end + 1):
        theSum += i
    print(theSum)   # 跟for同一級(jí)縮進(jìn)

# 調(diào)用函數(shù)
# 求1 - 100的和
calcSum(1,100)
#求300 - 400的和
calcSum(300,400)
# 求1 - 1000的和
calcSum(1,1000)

2 ~> 語法格式

2.1 創(chuàng)建函數(shù) / 定義函數(shù)

def 函數(shù)名(形參列表):
    函數(shù)體
    return 返回值

2.2 調(diào)用函數(shù) / 使用函數(shù)

函數(shù)名(實(shí)參列表)           // 不考慮返回值
返回值 = 函數(shù)名(實(shí)參列表)   // 考慮返回值

2.2.1 函數(shù)定義并不會(huì)執(zhí)行函數(shù)體內(nèi)容,必須要調(diào)用才會(huì)執(zhí)行:調(diào)用幾次就會(huì)執(zhí)行幾次

def test1():
    print('hello')
    
# 如果光是定義函數(shù), 而不調(diào)用, 則不會(huì)執(zhí)行. 

2.2.2 函數(shù)必須先定義,再使用

test3()          # 還沒有執(zhí)行到定義, 就先執(zhí)行調(diào)用了, 此時(shí)就會(huì)報(bào)錯(cuò). 
def test3():
    print('hello')

報(bào)錯(cuò)——

2.2.3 類比

在霓虹國的熱血?jiǎng)勇?,角色釋放技能之前,需要大喊招式的名字,比?ldquo;草帽小子”蒙奇·D·路飛每次使用惡魔果實(shí)力量時(shí)就會(huì)喊出“橡膠橡膠!XXX”,像角色先喊招式再放大招這個(gè)行為就可以理解為 “先定義, 再使用”。

2.3 最佳實(shí)踐

# 函數(shù)的定義和調(diào)用

# 返回值 = 函數(shù)名(實(shí)參列表)

# 先定義一個(gè)函數(shù)
# 如果只是定義,而不去調(diào)用,則函數(shù)體里面的代碼就不會(huì)執(zhí)行!
def test():
    print('Alice')
    print('Alice')
    print('Alice')

# 函數(shù)調(diào)用才會(huì)真正執(zhí)行函數(shù)體里面的代碼
# 函數(shù)經(jīng)過一次定義之后,可以被調(diào)用多次!
test()
test()
test()
test()
test()

# 運(yùn)行結(jié)果:
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice
# Alice

# Python中要求,函數(shù)定義寫在前面,函數(shù)調(diào)用寫在后面-->先定義,后調(diào)用

2.4 代碼警告的處理

# 代碼警告的處理
# 警告-->提示你的代碼可能存在問題,但是并不影響程序編譯執(zhí)行(比較嚴(yán)重)
# 錯(cuò)誤-->代碼中實(shí)打?qū)嵉挠袉栴}?。ǚ浅?yán)重!影響到代碼了)
# 這兩個(gè)事情嚴(yán)重程度是完全不同的!

# 定義一個(gè)求和函數(shù)
# 點(diǎn)擊[忽略這個(gè)“錯(cuò)誤(遠(yuǎn)不到錯(cuò)誤這個(gè)級(jí)別,只能說是警告)”]
def calcSum(beg, end):   # 報(bào)了警告
    theSum = 0  # 剛才是函數(shù)名,這里是變量名,我們同樣選擇[忽略]
    for i in range(beg,end + 1):
        theSum += i
    print(theSum)   # 跟for同一級(jí)縮進(jìn)

# 調(diào)用函數(shù)
# 求1 - 100的和
calcSum(1, 100)
#求300 - 400的和
calcSum(300, 400)
# 求1 - 1000的和
calcSum(1, 1000)
# 文件末尾建議加上空行

# PEP8,這是Pyhton里面一套非常流行的編程規(guī)范,也就是寫代碼中的一些“軟性要求”
# 未來咱們在公司里面究竟是使用啥樣的規(guī)范?不確定,只要代碼風(fēng)格干凈整潔即可。

3 ~> 函數(shù)參數(shù):實(shí)參、形參

3.1 概念

在函數(shù)定義的時(shí)候,可以在()中指定“形式參數(shù)”(簡稱形參),然后在調(diào)用的時(shí)候,由調(diào)用者把“實(shí)際參數(shù)’(簡稱實(shí)參)傳遞進(jìn)去。

這樣就可以做到:一份函數(shù),針對(duì)不同的數(shù)據(jù)進(jìn)行計(jì)算處理。

3.2 示例

我們結(jié)合一下前面的代碼示例——

def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)
    
sum(1, 100)
sum(300, 400)
sum(1, 1000)

上面的代碼中,beg,end就是函數(shù)的形參1,100 / 300,400就是函數(shù)的實(shí)參。

在執(zhí)行sum(1,100)的時(shí)候,就相當(dāng)于beg = 1,end = 100,然后在函數(shù)內(nèi)部就可以針對(duì)1 - 100進(jìn)行運(yùn)算。
在執(zhí)行sum(300,400)的時(shí)候,就相當(dāng)于beg = 300,end = 400,然后在函數(shù)內(nèi)部就可以針對(duì)300 - 400 進(jìn)行運(yùn)算。

實(shí)參和形參之間的關(guān)系,就像簽合同一樣。

甲方、乙方這就相當(dāng)于形參,艾莉絲、魯?shù)蠟跛咕褪菍?shí)參。

def 簽合同(甲方, 乙方):
 合同內(nèi)容....
簽合同('艾莉絲', '魯?shù)蠟跛?)
簽合同('艾莉絲', '希露菲')
簽合同('艾莉絲', '洛琪希')

3.3 注意

一個(gè)函數(shù)可以有一個(gè)形參,也可以有多個(gè)形參,也可以沒有形參。
一個(gè)函數(shù)的形參有幾個(gè),那么傳遞實(shí)參的時(shí)候也得傳幾個(gè),保證個(gè)數(shù)要匹配。

def test(a, b, c):
    print(a, b, c)
test(10)

和C++/Java不同,Python是動(dòng)態(tài)類型的編程語言,函數(shù)的形參不必指定參數(shù)類型.換句話說,一個(gè)函數(shù)可以支持多種不同類型的參數(shù)。

def test(a):
    print(a)
test(10)
test('hello')
test(True)

3.4 最佳實(shí)踐

3.4.1 實(shí)參

# 函數(shù)的參數(shù)(1)
# 形參和實(shí)參

def test(a,b,c):
    print(a,b,c)

test(10)    # 函數(shù)形參數(shù)量要和形參數(shù)量要匹配

3.4.2 形參

# 函數(shù)的參數(shù)(2)
# 形參和實(shí)參

# def test(a):
#     print(a)
#
# test(10)
# test('hello')
# test(True)

def add(a,b):
    return a + b

print(add(10,20))   # 整型相加
print(add(1.5,2.5)) # 浮點(diǎn)型相加
print(add('hello','world')) # 字符串相加
print(add(10,'hello'))  # 報(bào)錯(cuò),不能相加

4 ~> 函數(shù)返回值

4.1 概念

函數(shù)的參數(shù)可以視為是函數(shù)的“輸入”,則函數(shù)的返回值,就可以視為是函數(shù)的“輸出”。

此處的“輸入”,“輸出”是更廣義的輸入輸出,不是單純指通過控制臺(tái)輸入輸出。
我們可以把函數(shù)想象成一個(gè)“工廠",工廠需要買入原材料,進(jìn)行加工,并生產(chǎn)出產(chǎn)品。
函數(shù)的參數(shù)就是原材料,函數(shù)的返回值就是生產(chǎn)出的產(chǎn)品。

4.2 示例

4.2.1 示例代碼

def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    print(sum)
    
calc(1, 100)

這段代碼可以可以轉(zhuǎn)換成——

def calcSum(beg, end):
    sum = 0
    for i in range(beg, end + 1):
        sum += i
    return sum
result = calcSum(1, 100)
print(result)

這兩個(gè)代碼的區(qū)別就在于,前者直接在函數(shù)內(nèi)部進(jìn)行了打印,后者則使用 return 語句把結(jié)果返回給函數(shù)調(diào)用者,再由調(diào)用者負(fù)責(zé)打印。

我們一般傾向于第二種寫法。

實(shí)際開發(fā)中我們的一個(gè)通常的編程原則,是“邏輯和用戶交互分離”而第一種寫法的函數(shù)中,既包含了計(jì)算邏輯,又包含了和用戶交互(打印到控制臺(tái)上),這種寫法是不太好的,如果后續(xù)我們需要的是把計(jì)算結(jié)果保存到文件中,或者通過網(wǎng)絡(luò)發(fā)送,或者展示到圖形化界面里,那么第一種寫法的函數(shù),就難以勝任了。

而第二種寫法則專注于做計(jì)算邏輯,不負(fù)責(zé)和用戶交互,那么就很容易把這個(gè)邏輯搭配不同的用戶交互代碼,來實(shí)現(xiàn)不同的效果。

4.2.2 一個(gè)函數(shù)中可以有多個(gè)return語句

# 判定是否是奇數(shù)
def isOdd(num):
    if num % 2 == 0:
        return False
    else:
        return True
  
result = isOdd(10)
print(result)

4.2.3 執(zhí)行到return語句,函數(shù)就會(huì)立即執(zhí)行結(jié)束,回到調(diào)用位置

# 判定是否是奇數(shù)
def isOdd(num):
    if num % 2 == 0:
        return False
    return True
result = isOdd(10)
print(result)

如果num是偶數(shù),則進(jìn)入 if 之后,就會(huì)觸發(fā)return False,也就不會(huì)繼續(xù)執(zhí)行return True

4.2.4 一個(gè)函數(shù)是可以一次返回多個(gè)返回值的,使用來分割多個(gè)返回值

4.2.5 一個(gè)函數(shù)是可以一次返回多個(gè)返回值的,使用_來分割多個(gè)返回值

def getPoint():
    x = 10
    y = 20
    return x, y
_, b = getPoint()

4.3 最佳實(shí)踐

# 函數(shù)的返回值(1)

# 求beg,end這個(gè)范圍的整數(shù)之和
def calSum(beg, end):
    theSum = 0
    for i in range(beg,end + 1):
        theSum += i
    return theSum

result = calSum(1,100)
print(result)
# 函數(shù)的返回值(2)

# 這種情況下,不算是有多個(gè) return 語句
# def test1():
#     return 1
#     return 2

# 一般多個(gè) return 語句是搭配分支/循環(huán)語句的

# def isOdd(num):
#     """
#     用來判定 num 是不是奇數(shù),如果是奇數(shù)就返回 True,不是就返回 False
#     :param num:要判定的整數(shù)
#     :return:返回 True False 表示是不是奇數(shù)
#     """
#     # 第一種寫法
#     # if num % 2 == 0:
#     #     return True
#     # else:
#     #     return False
#
#     # 第二種寫法
#     if num % 2 == 0:
#         return False
#     return True
#
# print(isOdd(10))
# print(isOdd(19))

# 寫一個(gè)函數(shù),返回平面上的一個(gè)點(diǎn)
# 橫坐標(biāo),縱坐標(biāo)
def getPoint():
    x = 10
    y = 20
    return x,y

a,b = getPoint()
print(a,b)

5 ~> 變量作用域

5.1 示例

觀察下面的代碼——

def getPoint():
    x = 10
    y = 20
    return x, y
x, y = getPoint()

在這個(gè)代碼中,函數(shù)內(nèi)部存在x,y,函數(shù)外部也有x,y,但是這兩組x、y不是相同的變量,而只是恰好有一樣的名字。

5.2 理論

5.2.1 變量只能在所在的函數(shù)內(nèi)部生效

在函數(shù)getPoint內(nèi)部定義的x、y只是在函數(shù)內(nèi)部生效,一旦出了函數(shù)的范圍,這兩個(gè)變量就不再生效。

def getPoint():
    x = 10
    y = 20
    return x, y
getPoint()
print(x, y)

5.2.2 在不同的作用域中,允許存在同名的變量

雖然 名字相同,實(shí)際上是不同的變量。

x = 20
def test():
    x = 10
    print(f'函數(shù)內(nèi)部 x = {x}')
test()
print(f'函數(shù)外部 x = {x}')

注意:
在函數(shù)內(nèi)部的變量,也稱為“局部變量”;
不在任何函數(shù)內(nèi)部的變量,也稱為“全局變量”。

5.2.3 如果函數(shù)內(nèi)部嘗試訪問的變量在局部不存在,就會(huì)嘗試去全局作用域中查找

x = 20
def test():
    print(f'x = {x}')
test()

5.2.4 如果是想在函數(shù)內(nèi)部,修改全局變量的值,需要使用global關(guān)鍵字聲明

x = 20
def test():
    global x
    x = 10
    print(f'函數(shù)內(nèi)部 x = {x}')
test()
print(f'函數(shù)外部 x = {x}')

如果此處沒有global,則函數(shù)內(nèi)部的x = 10就會(huì)被視為是創(chuàng)建一個(gè)局部變量x,這樣就和全局變量x不相關(guān)了。

5.2.5 if / while / for等語句塊不會(huì)影響到變量作用域

換而言之,在if / while / for中定義的變量,在語句外面也可以正常使用。

for i in range(1, 10):
    print(f'函數(shù)內(nèi)部 i = {i}')
print(f'函數(shù)外部 i = {i}')

5.3 最佳實(shí)踐

# 變量的作用域

# 函數(shù)里面的x,y和函數(shù)外面的x,y是同一組變量嗎?
# 不同的變量,只不過名字恰好相同!
# def getPoint():
#     x = 10
#     y = 20
#     return x,y

# 函數(shù)內(nèi)部的變量名,只能在函數(shù)內(nèi)部生效,出了函數(shù),就無效了!
# x,y = getPoint()
# print(x,y)
# 變量的作用域!
# 一個(gè)變量名的生效范圍是一定的!只在一個(gè)固定的區(qū)域內(nèi)生效

# def getPoint():
#     x = 10
#     y = 20
#     return x,y
#
# getPoint()
# print(x,y)
# 函數(shù)內(nèi)部的x,y不生效-->NameError: name 'x' is not defined
# 函數(shù)內(nèi)部和函數(shù)外部是可以使用同名的變量的,雖然變量名相同,但是是不同的變量!

# 全局變量和局部變量

# 例子:

# x = 10
#
# def test():
#     x = 20
#     print(f"函數(shù)內(nèi)部:{x}")
#
# test()
# print(f"函數(shù)外部:{x}")

# 函數(shù)里,也是可以使用全局變量的!
# 例子:在函數(shù)里嘗試讀取全局變量是可以的!

# x = 10
#
# def test():
#     print(f"x = {x}")
#
# test()

# x = 10
#
# def test():
#     print(f"函數(shù)內(nèi)部:{x}")
#
# test()
# print(f"函數(shù)外部:{x}")
# 在函數(shù)中嘗試訪問某個(gè)變量的時(shí)候,會(huì)先嘗試在局部變量中查找,如果找到,就直接訪問;
# 如果沒找到,就會(huì)往上一級(jí)作用域中進(jìn)行查找-->test再往上一級(jí)作用域,就是全局了

# 使用這個(gè)函數(shù),把全局變量 x 給改成 20!

# x = 10
#
# def test():
#     x = 20  # 這個(gè)x被當(dāng)成函數(shù)內(nèi)部的局部變量了
#
# test()
# print(f"x = {x}")

# Python中的關(guān)鍵字:global
# x = 10
#
# def test():
#     # 聲明,變成針對(duì)全局變量來進(jìn)行的了
#     global x
#     x = 20  # 這個(gè)x被當(dāng)成函數(shù)內(nèi)部的局部變量了
#     # 由于修改全局變量的操作和創(chuàng)建變量的語法是一模一樣的,所以Python把它當(dāng)做是局部變量了
#     # (所以要加上 global 進(jìn)行顯式聲明)
#
# test()
# print(f"x = {x}")
# 沒有 global ,此時(shí)就會(huì)把x = 20當(dāng)做是在函數(shù)內(nèi)部創(chuàng)建了一個(gè)局部變量 x
# 而實(shí)際上是要修改全局變量 x ,為了讓函數(shù)里面知道 x 是個(gè)全局變量,就使用 global 關(guān)鍵字先聲明一下
# if else,while,for這些關(guān)鍵字也會(huì)引入“代碼塊”,但是這些代碼塊不會(huì)對(duì)變量的作用域產(chǎn)生影響!!
# 在上述語句代碼塊內(nèi)部定義的變量,可以在外面被訪問!

# for i in range(1,11):
#     print(i)
#
# print('------------------------')
# print(i)
# 輸出:
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10
# ------------------------
# 10

if True:
    x = 10

print(x)

6 ~> 函數(shù)執(zhí)行過程

6.1 概念

調(diào)用函數(shù)才會(huì)執(zhí)行函數(shù)體代碼,不調(diào)用則不會(huì)執(zhí)行。

函數(shù)體執(zhí)行結(jié)束(或者遇到return語句)則回到函數(shù)調(diào)用位置,繼續(xù)往下執(zhí)行。

6.2 示例

def test():
    print("執(zhí)行函數(shù)內(nèi)部代碼")
    print("執(zhí)行函數(shù)內(nèi)部代碼")
    print("執(zhí)行函數(shù)內(nèi)部代碼")
print("1111")
test()
print("2222")
test()
print("3333")

6.3 打斷點(diǎn)

6.3.1 調(diào)試器觀察函數(shù)執(zhí)行過程

這個(gè)過程還可以使用PyCharm自帶的調(diào)試器來觀察。

點(diǎn)擊行號(hào)右側(cè)的空白,可以在代碼中插入 斷點(diǎn)。
右鍵,Debug,可以按照調(diào)試模式執(zhí)行代碼,每次執(zhí)行到斷點(diǎn),程序都會(huì)暫停下來。
使用StepInto (F7) 功能可以逐行執(zhí)行代碼。

6.3.2 舉個(gè)例子

6.4 最佳實(shí)踐

# 函數(shù)的執(zhí)行過程

def test():
    print('執(zhí)行函數(shù)體代碼')
    print('執(zhí)行函數(shù)體代碼')
    print('執(zhí)行函數(shù)體代碼')

print("111111")
test()
print("222222")
test()
print("333333")
test()
print("444444")
test()
print("555555")
test()
# 還可以使用PyCharm的調(diào)試器,也能觀察函數(shù)執(zhí)行的過程
# 調(diào)試執(zhí)行相比于正常的區(qū)別:就是可以隨時(shí)停下來,方便程序員觀察程序的中間過程

# 調(diào)試:F7,step into

7 ~> 鏈?zhǔn)秸{(diào)用和嵌套調(diào)用

7.1 鏈?zhǔn)秸{(diào)用

7.1.1 示例

# 判定是否是奇數(shù)
def isOdd(num):
    if num % 2 == 0:
        return False
    else:
        return True
  
result = isOdd(10)
print(result)

實(shí)際上也可以簡化一下,寫作——

print(isOdd(10))

7.1.2 概念

把一個(gè)函數(shù)的返回值,作為另一個(gè)函數(shù)的參數(shù),這種操作稱為 鏈?zhǔn)秸{(diào)用。

這是一種比較常見的寫法。

7.1.3 最佳實(shí)踐

# 函數(shù)的鏈?zhǔn)秸{(diào)用和嵌套調(diào)用(1)

# 鏈?zhǔn)秸{(diào)用
def isOdd(num):
    if num % 2 == 0:
        return False
    return True

def add(x,y):
    return x + y

# result = isOdd(10)
# print(result)

print(isOdd(add(5,5)))

7.2 嵌套調(diào)用

7.2.1 概念

函數(shù)內(nèi)部還可以調(diào)用其他的函數(shù),這個(gè)動(dòng)作稱為 “嵌套調(diào)用”。

test函數(shù)內(nèi)部調(diào)用了print函數(shù),這里就屬于嵌套調(diào)用。

7.2.2 一個(gè)函數(shù)里面可以嵌套調(diào)用任意多個(gè)函數(shù)

函數(shù)嵌套的過程是非常靈活的。

def a():
    print("函數(shù) a")
def b():
    print("函數(shù) b")
    a()
def c():
    print("函數(shù) c")
    b()
def d():
    print("函數(shù) d")
    c()
d()

如果把代碼稍微調(diào)整,打印結(jié)果則可能發(fā)生很大變化。

def a():
    print("函數(shù) a")
def b():
    a()
    print("函數(shù) b")
def c():
    b()
    print("函數(shù) c")
def d():
    c()
    print("函數(shù) d")
d()

注意體會(huì)上述代碼的執(zhí)行順序,我們可以通過畫圖的方式來理解。

函數(shù)之間的調(diào)用關(guān)系,在Python中會(huì)使用一個(gè)特定的數(shù)據(jù)結(jié)構(gòu)來表示,稱為 函數(shù)調(diào)用棧。每次函數(shù)調(diào)用,都會(huì)在調(diào)用棧里新增一個(gè)元素,稱為 棧幀。

可以通過PyCharm調(diào)試器看到函數(shù)調(diào)用棧和棧幀。
在調(diào)試狀態(tài)下,PyCharm左下角一般就會(huì)顯示出函數(shù)調(diào)用棧。

7.2.3 每個(gè)函數(shù)的局部變量,都包含在自己的棧幀中

def a():
    num1 = 10
    print("函數(shù) a")
def b():
    num2 = 20
    a()
    print("函數(shù) b")
def c():
    num3 = 30
    b()
    print("函數(shù) c")
def d():
    num4 = 40
    c()
    print("函數(shù) d")
d()

選擇不同的棧幀,就可以看到各自棧幀中的局部變量。

思考: 上述代碼,a,b,c,d函數(shù)中的局部變量名各不相同.如果變量名是相同的,比如都是 num,那么
這四個(gè)函數(shù)中的num是屬于同一個(gè)變量,還是不同變量呢?

7.2.4 最佳實(shí)踐

# 函數(shù)的鏈?zhǔn)秸{(diào)用和嵌套調(diào)用(2)

# 嵌套調(diào)用

# def test():
#     print("Alice")
#
# test()

# 嵌套調(diào)用層次可以有很多層

# def a():
#     print('函數(shù) a')
#
# def b():
#     print('函數(shù) b')
#     a()
#
# def c():
#     print('函數(shù) c')
#     b()
#
# def d():
#     print('函數(shù) d')
#     c()
#
# d()
# # 運(yùn)行結(jié)果
# 函數(shù) d
# 函數(shù) c
# 函數(shù) b
# 函數(shù) a

# 代碼順序稍作調(diào)整,打印順序就會(huì)變化

def a():
    print('函數(shù) a')

def b():
    a()
    print('函數(shù) b')

def c():
    b()
    print('函數(shù) c')

def d():
    c()
    print('函數(shù) d')

d()
# # 運(yùn)行結(jié)果
# 函數(shù) a
# 函數(shù) b
# 函數(shù) c
# 函數(shù) d

8 ~> 局部變量和函數(shù)棧幀

8.1 概念

8.2 最佳實(shí)踐

# 局部變量和函數(shù)棧幀

# 這幾個(gè)變量雖然同名,但是是不同變量,屬于不同的函數(shù)作用域
# 每個(gè)變量也是保存在各自的棧幀中的(每個(gè)棧幀也是保存在內(nèi)存中)
# 變量本質(zhì)是一塊內(nèi)存空間

def a():
    num = 10
    print('函數(shù) a')

def b():
    num = 20
    a()
    print('函數(shù) b')

def c():
    num = 30
    b()
    print('函數(shù) c')

def d():
    num = 40
    c()
    print('函數(shù) d')

d()

9 ~> 函數(shù)遞歸

9.1 函數(shù)遞歸的概念

遞歸是嵌套調(diào)用中的一種特殊情況:即一個(gè)函數(shù)嵌套調(diào)用自己。

9.2 示例:遞歸計(jì)算5!

def factor(n):
    if n == 1:
        return 1
    return n * factor(n - 1)
result = factor(5)
print(result)

上述代碼中,就屬于典型的遞歸操作。在 factor 函數(shù)內(nèi)部,又調(diào)用了 factor 自身。

注意:遞歸代碼務(wù)必要保證——

(1)存在遞歸結(jié)束條件:比如if n == 1就是結(jié)束條件,當(dāng)n為1的時(shí)候,遞歸就結(jié)束了;
(2)每次遞歸的時(shí)候,要保證函數(shù)的實(shí)參是逐漸逼近結(jié)束條件的。

如果上述條件不能滿足,就會(huì)出現(xiàn)“無限遞歸”,這是一種典型的代碼錯(cuò)誤。

def factor(n):
    return n * factor(n - 1)
result = factor(5)
print(result)

正如前面所描述的那樣,函數(shù)調(diào)用時(shí)會(huì)在函數(shù)調(diào)用棧中記錄每一層函數(shù)調(diào)用的信息。

但是函數(shù)調(diào)用棧的空間不是無限大的,如果調(diào)用層數(shù)太多,就會(huì)超出棧的最大范圍,導(dǎo)致出現(xiàn)問題。

9.3 最佳實(shí)踐

# 函數(shù)遞歸
# 寫一個(gè)函數(shù),來求 n 的階乘(n 是正整數(shù))
# 用循環(huán)的方式來寫
# def factor(n):
#     result = 1
#     for i in range(1,n + 1):
#         result *= i
#     return result
#
# print(factor(5))
# 用遞歸的方式來寫
# n! => n * (n - 1)
# 1! => 1
def factor(n):
    if n == 1:
        return  1
    return n * factor(n - 1)
print(factor(5))

9.4 遞歸的優(yōu)缺點(diǎn)

9.4.1 遞歸的優(yōu)點(diǎn)

(1)遞歸類似于“數(shù)學(xué)歸納法”,明確初始條件,和遞推公式,就可以解決一系列的問題;

(2)遞歸代碼往往代碼量非常少。

9.4.2 遞歸的缺點(diǎn)

(1)遞歸代碼往往難以理解,很容易超出掌控范圍;

(2)遞歸代碼容易出現(xiàn)棧溢出的情況;

(3)遞歸代碼往往可以轉(zhuǎn)換成等價(jià)的循環(huán)代碼,并且通常來說循環(huán)版本的代碼執(zhí)行效率要略高于遞歸版本。

9.4.3 基于遞歸的優(yōu)缺點(diǎn),使用遞歸的結(jié)論

在我們實(shí)際開發(fā)的時(shí)候,使用遞歸要慎重!

10 ~> 參數(shù)默認(rèn)值

10.1 概念

Python中的函數(shù),可以給形參指定默認(rèn)值。

帶有默認(rèn)值的參數(shù),可以在調(diào)用的時(shí)候不傳參。

10.2 最佳實(shí)踐

10.2.1 代碼示例:計(jì)算兩個(gè)數(shù)字的和

def add(x, y, debug=False):
    if debug:
        print(f'調(diào)試信息: x={x}, y={y}')
    return x + y
print(add(10, 20))
print(add(10, 20, True))

此處debug=False即為參數(shù)默認(rèn)值。當(dāng)我們不指定第三個(gè)參數(shù)的時(shí)候,默認(rèn)debug的取值即為False。

10.2.2 帶有默認(rèn)值的參數(shù)需要放到?jīng)]有默認(rèn)值的參數(shù)的后面

def add(x, debug=False, y):
    if debug:
        print(f'調(diào)試信息: x={x}, y={y}')
    return x + y
print(add(10, 20))

帶有默認(rèn)值的參數(shù)如果沒有放到?jīng)]有默認(rèn)值的參數(shù)的后面就會(huì)報(bào)錯(cuò)——

10.2.3 實(shí)踐

# 函數(shù)形參的默認(rèn)值
# 通過這樣的默認(rèn)值,就可以讓函數(shù)的設(shè)計(jì)更靈活!
# debug:形參的默認(rèn)值
# 帶有默認(rèn)值的形參就可以在調(diào)用函數(shù)的時(shí)候,不必傳參
# 參數(shù)越多會(huì)提高使用者的成本
def add(x ,y ,debug=False):
    if debug:
        print(f'x = {x},y = {y}')
    return x + y
# result = add(10,20) # 不開啟調(diào)試信息的情況,只傳了兩個(gè)實(shí)參
result = add(10,20,True)
# result = add(10,20,False)
print(result)
# 像默認(rèn)值這樣的語法,在編程界是存在爭議的!
# C++也支持形參默認(rèn)參數(shù),Java就不支持,但是Python還是引入默認(rèn)參數(shù)的
# 帶有默認(rèn)值的形參得在形參列表的后面,而不能在前面 / 中間!
# 多個(gè)帶有默認(rèn)值的形參,這些都得在形參列表的后面
# 報(bào)錯(cuò):SyntaxError: parameter without a default follows parameter with a default

11 ~> 關(guān)鍵字參數(shù)

11.1 概念

在調(diào)用函數(shù)的時(shí)候,需要給函數(shù)指定實(shí)參,一般默認(rèn)情況下是按照形參的順序,來依次傳遞實(shí)參的,但是我們也可以通過 關(guān)鍵字參數(shù),來調(diào)整這里的傳參順序,顯式指定當(dāng)前實(shí)參傳遞給哪個(gè)形參。

11.2 示例

def test(x, y):
    print(f'x = {x}')
    print(f'y = {y}')
test(x=10, y=20)
test(y=100, x=200)

運(yùn)行結(jié)果如下所示——

11.3 最佳實(shí)踐

# 函數(shù)的關(guān)鍵字參數(shù)

# 按照先后順序來傳參——這種傳參風(fēng)格,稱為“位置參數(shù)”    這是各個(gè)編程語言中最普遍的方式!
# 關(guān)鍵字傳參:按照形參的名字來進(jìn)行傳參!
def test(x,y):
    print(f'x = {x}')
    print(f'y = {y}')

test(x=10,y=20) # 非常明顯地告訴程序員:你的參數(shù)要傳給誰!另外可以無視形參和實(shí)參的順序!
test(y=100,x=200)
# 運(yùn)行結(jié)果
# x = 10
# y = 20
# x = 200
# y = 100

# 位置參數(shù)和關(guān)鍵字參數(shù)還能混著用,只不過混著用的時(shí)候要求位置參數(shù)在前。
# 關(guān)鍵字參數(shù)在后
# 關(guān)鍵字參數(shù)一般也就是搭配默認(rèn)參數(shù)來使用的
# 一個(gè)函數(shù),可以提供很多的參數(shù),來實(shí)現(xiàn)對(duì)這個(gè)函數(shù)的內(nèi)部功能做出一些調(diào)整設(shè)定
# 為了降低調(diào)用者的使用成本,就可以把大部分參數(shù)設(shè)定出默認(rèn)值
# 當(dāng)調(diào)用者需要調(diào)整其中的一部分參數(shù)的時(shí)候,就可以搭配關(guān)鍵字參數(shù)來進(jìn)行操作(在Python的文件操作部分會(huì)演示,這里不展開)

12 ~> Python基礎(chǔ)語法:函數(shù)部分小結(jié)

函數(shù)是編程語言中的一個(gè)核心語法機(jī)制。Python中的函數(shù)和大部分編程語言中的函數(shù)功能都是基本類似的。

我們當(dāng)下最關(guān)鍵要理解的主要就是三個(gè)點(diǎn):

函數(shù)的定義
函數(shù)的調(diào)用
函數(shù)的參數(shù)傳遞

在后續(xù)的編程中,我們會(huì)廣泛的使用到函數(shù),uu們要再反復(fù)加深對(duì)于函數(shù)的理解哦。

# 函數(shù)部分小結(jié)
# 函數(shù)的定義
# 函數(shù)的調(diào)用
# 函數(shù)的參數(shù)傳遞過程
# 函數(shù)的執(zhí)行流程:
# (1)進(jìn)去,好進(jìn)
# (2)出來,不好出

結(jié)尾

到此這篇關(guān)于Python函數(shù)定義、參數(shù)、返回值與作用域的文章就介紹到這了,更多相關(guān)Python函數(shù)詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

邵阳县| 湟源县| 霍州市| 响水县| 梁平县| 舟曲县| 扶绥县| 海林市| 教育| 普定县| 双鸭山市| 鹤岗市| 江津市| 浦城县| 安新县| 黄山市| 监利县| 紫金县| 囊谦县| 新乐市| 舟山市| 稻城县| 大姚县| 佛坪县| 牟定县| 绥宁县| 定兴县| 兴仁县| 兰考县| 金华市| 正镶白旗| 将乐县| 宁晋县| 长寿区| 运城市| 司法| 万山特区| 磐安县| 祁连县| 高平市| 宜都市|