python--------函數【定義、調用、傳遞參數、遞歸函數】

1.什麼是函數

  • 函數(function)由若干條語句組成,用於實現特定的功能
  • 函數的本質就是對功能的封裝
  • 一旦定義了函數,就可以在程序中需要實現該功能的位置調用函數
  • 函數名不能重複(沒有重載)

2.定義和調用函數

  • 使用def關鍵字來創建python自定義函數
  • 可以直接使用函數名來調用函數

語法結構:

def 函數名 (參數列表)
    函數體
    return 數據
  • 參數列表可以爲空,也可以包含多個參數
  • return 可寫可不寫,不寫默認返回None

<1> 定義一個空函數

def test():
    pass

<2> 無參函數

def test():
    print('in test')
test()

運行結果

in test

儘管定義了函數,只要不調用函數,那這個函數是不會執行的

def hh():
    print('hello')
 #沒有調用這個函數,該函數不執行

<3> 有參函數 (參數—argument/arg)

def test1(arg):
    print('in test')
test1(1)

def test2(arg):
    print('in test',arg)
    #參數類型沒有要求,可以是任意類型
test2(1)
test2('hello')
test2([100,200])

def test3(arg,arg1,arg2):
    print('in test',arg,arg1,arg2)
    # 1-->arg  python-->arg1  [1,2]-->arg2
test3(1,'python',[1,2])

運行結果

in test
in test 1
in test hello
in test [100, 200]
in test 1 python [1, 2]
  • 參數類型沒有要求,可以是任意類型
  • 參數的個數沒有要求

3. 返回值

def test(arg,arg1,arg2):
    print('in test',arg,arg1,arg2)
    return 1  #返回1
ret=test(1,2,3)   #調用test(1,2,3)函數,然後把返回值給ret變量
print(ret)

運行結果

in test 1 2 3
1

可以返回任何類型

def test1(arg,arg1,arg2):
    print('in test1',arg,arg1,arg2)
    return [4,5]
ret=test1(1,2,3)
print(ret)

def test2(arg,arg1,arg2):
    print('in test2',arg,arg1,arg2)
    return [arg,arg1,arg2]
ret=test2(1,2,3)
print(ret)

運行結果

in test1 1 2 3
[4, 5]
in test2 1 2 3
[1, 2, 3]

如果沒有return那麼就返回None return|return None |不寫

def test3(arg,arg1,arg2):
    print('in test3',arg,arg1,arg2)
ret=test3(1,2,3)
print(ret)


def test4(arg,arg1,arg2):
    print('in test4',arg,arg1,arg2)
    return
ret=test4(1,2,3)
print(ret)

def test5(arg,arg1,arg2):
    print('in test5',arg,arg1,arg2)
    return None
ret=test5(1,2,3)
print(ret)

運行結果

in test3 1 2 3
None
in test4 1 2 3
None
in test5 1 2 3
None
def test1():
    print('in the test1')
def test():
    print('in the test')
    return test1    #返回test1()的內存地址
res=test()
print(res())  #test1()

#因爲test1沒有return 所以默認返回None

運行結果

in the test
in the test1
None

練習題:

#我們系統函數test6 如果都是整數 那麼返回數組[1,2,3]
#如果參數全是字符串 就返回 arg arg1 arg2 'welcome to python'

def test6(arg,arg1,arg2):
    #判斷參數的類型
    #isinstance 是系統的 用來判斷參數是否是你想要的那個類型
    if isinstance(arg,int) and isinstance(arg1,int) and isinstance(arg2,int):
        return [arg,arg1,arg2]
    if isinstance(arg,str) and isinstance(arg1,str) and isinstance(arg2,str):
        return arg+' '+arg1+' '+arg2
    #如果參數並不都是整數或者並不都是字符串,那就返回'Error'
    return 'Error'
c=test6(1,2,3)
print(c)
c=test6('welcome','to','python')
print(c)
c=test6(1,2,'python')
print(c)

運行結果

[1, 2, 3]
welcome to python
Error

4.形參和實參

形參:

  • 形參變量只有在被調用時才分配內存單元,在調用結束時,即可釋放預分配的內存單元
  • 形參只在函數內部有效
  • 函數調用結束返回主調用函數後則不能再使用該形參變量

實參:

  • 實參可以是常量、變量、表達式、函數等
  • 無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳遞給形參
  • 應預先用賦值,輸入等辦法是參數獲得確定值
def calc(x,y): #x,y是形參
    res=x**y
    return res
c=calc(2,3)   #2,3是實參
#有人想這個不就是 x=2,y=3的賦值操作,那就可以直接輸出x,y
#但是不要忘了形參只有在被調用時才分配內存單元
#print(x)   錯誤
#print(y)   錯誤
print(c)

運行結果

8

5.函數參數

def test7(name,age,score):
    print(name,age,score)

<1>普通參數

test7('yang',18,80)

運行結果

yang 18 80

普通參數的參數順序不能改變

tset7(18,'yang',80)  是錯的

<2> 關鍵字參數

順序可以隨便設置

test7(name='yang',age=18,score=80)
test7(age=18,score=80,name='yang')

運行結果

yang 18 80
yang 18 80

<3> 普通參數和關鍵字參數混合使用

  • 注意python要求 普通參數和關鍵字參數如果混合使用那麼你必須先傳普通參數,然後再傳關鍵字參數
test7('yang',18,score=80)
test7('yang',age=18,score=80)
test7(name='yang',age=18,score=80)
#test7('yang',age=18,80)   錯誤
#test7('yang',70,age=18)    錯誤  70傳給age而後面的參數又給age賦值了一個數,那就沒有參數傳給score了

運行結果

yang 18 80
yang 18 80
yang 18 80

<4>默認參數

def test8(name,age,score=60):
    print(name,age,score)
#因爲已經有一個參數有了默認值,所以我們傳入兩個參數就可以
test8('yang',18)
#當然也可以傳三個參數,但是已經默認的那個參數如果也要傳的話,它會自動變爲傳入的數值
test8('yang',18,70)

運行結果

yang 18 60
yang 18 70

默認參數後面不能有普通參數

def test9(name,age=18,score=80):
    print(name,age,score)
test9('yang')
# def test9(name,age=18,score):    錯誤

運行結果

yang 18 80

<5> 可變長參數

(1) *args

  • *args表示一個可變元組
  • args就是一個元組 元組就是隻讀的數組/列表
  • 參數名就是args
  • *表示 args裏面的參數可變
def test10(*args):
    print(args)
test10(1,2,3)   #可以隨便添加參數

運行結果

(1, 2, 3)
def test11(*args):
    print(args,type(args)) #只輸出args的值和類型
    value=0
    for i in args: #因爲args是一個元組,所以需要遍歷才能獲取每個元素
        value+=i
    return value
c=test11(1,2,3,4)
print(c)
c=test11()   #沒有給args傳值
print(c)

運行結果

(1, 2, 3, 4) <class 'tuple'>
10
() <class 'tuple'>
0

這個可變參數 前面兩個參數v1,v2是默認參數,後面的參數是可變的

def test12(v1,v2,*args):
    print(args,type(args))  #只輸出args的值和類型
    value=0
    for i in args:
        value+=i
    return value
c=test12(1,2)    #v1=1,v2=2,沒有給args傳值
print(c)

運行結果

() <class 'tuple'>
0
def test13(v1,v2,*args):
    print(args,type(args))   #只輸出args的值和類型
    value=0
    for i in args:
        value+=i
    return value
c=test13(1,2,3)    #v1=1,v2=2,args=3
print(c)

運行結果

(3,) <class 'tuple'>
3
def test14(v1,v2,*args):
    print(args,type(args))   #輸出args和args的類型
    value=(v1+v2)    #value不像前兩個賦值爲0,現在的value已經把v1,v2提前加起來了
    for i in args:
        value+=i
    return value
c=test14(1,2,3)    #v1=1,v2=2,args=3
print(c)

運行結果

(3,) <class 'tuple'>
6

可變參數傳數組/列表
*list1就是args

def test14(v1,v2,*args):
    print(args,type(args))   #輸出args和args的類型
    value=(v1+v2)    #value不像前兩個賦值爲0,現在的value已經把v1,v2提前加起來了
    for i in args:
        value+=i
    return value
list1=[1,2,3,4]
c=test14(1,2,1,100,*list1)   #v1=1 v2=2 1,100,*list1就是args
#上面的相當於拆成 c=test14(1,2,1,100,1,2,3,4)
print(c)
(1, 100, 1, 2, 3, 4) <class 'tuple'>
114

(2) **kwargs

  • 可變參數處理關鍵字參數
  • kwargs表示 關鍵字可變參數
  • *表示普通可變參數(positional 位置參數)
  • ** 表示關鍵字可變參數
  • kwargs是一個字典
def test15(**kwargs):
    print(kwargs,type(kwargs))
    value=0
    for key in kwargs:
        v=kwargs[key]  #獲取字典裏的值
        if isinstance(v,int) or isinstance(v,float): #如果v是整數或者是浮點數那就執行下面的加法運算
            value+=v
    return value
test15(name='yang')
c=test15(name=10,b=1,c=2,d=3,e=4,f=100.56)
print(c)

運行結果

{'name': 'yang'} <class 'dict'>
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56} <class 'dict'>
120.56

可變參數支持位置參數/普通參數和關鍵字參數

def test16(*args,**kwargs):
    print(args)
    print(kwargs)
    value=0
    return  value
c=test16(1,2,3,name=10,b=1,c=2,d=3,e=4,f=100.56)
print(c)

運行結果

(1, 2, 3)
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56}
0
def test17(*args,**kwargs):
    print(args)
    print(kwargs)
    value=0
    #先處理位置參數/普通參數
    for i in args:    #遍歷元組
        value+=i
    for i in kwargs:   #遍歷字典
        v=kwargs[i]
        value+=v
    return  value
c=test17(1,2,3,name=10,b=1,c=2,d=3,e=4,f=100.56)  #若有字符串的參數還需要判斷並不參與加法運算
print(c)

運行結果

(1, 2, 3)
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56}
126.56

參數解開

dict2={'name':10,'b':1,'c':2,'d':3,'e':4,'f':100.56}
tuple2=(1,2,3)
# *tuple2 表示把(1,2,3)---->1,2,3
# **dict2 表示把{'name':10,'b':1,'c':2,'d':3,'e':4,'f':100.56}--->name=10,b=1,c=2,d=3,e=4,f=100.56
#  **的作用就是把dict2從字典轉換成關鍵字參數
c=test17(*tuple2,**dict2)
print(c)

運行結果

(1, 2, 3)
{'name': 10, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 100.56}
126.56

6.遞歸函數

遞歸函數是指直接或間接調用函數本身的函數

遞歸特性

  • 必須有一個明確的結束條件
  • 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少
  • 遞歸效率不高,遞歸層次過多會導致棧溢出
  • 在計算機中,函數調用時通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的。所以,遞歸調用的次數過多,會導致棧溢出

使用遞歸函數計算階乘

def fact(n):
    if n==1:
        return 1
    return n*fact(n-1)
print(fact(5))    #5*4*3*2*1

運行結果

120
def calc(n):
    print(n)
    if int(n/2)==0:
        return n
    res=calc(int(n/2))
    return res
calc(10)

運行結果

10
5
2
1
def calc1(n):
    print(n)
    if int(n/2)==0:
        return n
    res=calc1(int(n/2))
    return res
res=calc1(10)
print(res)

運行結果

10
5
2
1
1

在這裏插入圖片描述
res的值就是最後得到的1

遞歸函數相當於問路,我問1號朋友怎麼去目的地,1號不知道他去2號,2號不知道他去問3號,3號說我知道怎麼走,這時,我們還要返回正確路線給問路人我,3號告訴2號,2號告訴1號,1號再傳達給我

person_list=['小明','小李','小紅','小藍']
def ask_way(person_list):
    print('-'*60)    #打印一條分界線
    if len(person_list)==0:   #到最後一個人還不知道怎麼走
        return '沒人知道'
    person=person_list.pop(0)  #每次都把列表裏的第0個元素刪除並賦值給person
    if person=='小紅':     #小紅知道正確的路線
        return '%s說:我知道路,左走一百米就到了'%person
    print('hi 美女[%s],請問你知道華林在哪嗎?'%person) #每當問到一個人就輸出這句話
    print('%s回答道:不好意思,我不是很清楚,我幫你問問%s...'%(person,person_list))
    res=ask_way(person_list)   #把繼續問的人的結果賦值給res,當結果問到時就一層一層的返回給問路的人,並輸出下面的話
    print('%s問的結果是:%res'%(person,res))
    return res
res=ask_way(person_list)
print(res)

運行結果

------------------------------------------------------------
hi 美女[小明],請問你知道華林在哪嗎?
小明回答道:不好意思,我不是很清楚,我幫你問問['小李', '小紅', '小藍']...
------------------------------------------------------------
hi 美女[小李],請問你知道華林在哪嗎?
小李回答道:不好意思,我不是很清楚,我幫你問問['小紅', '小藍']...
------------------------------------------------------------
小李問的結果是:'小紅說:我知道路,左走一百米就到了'es
小明問的結果是:'小紅說:我知道路,左走一百米就到了'es
小紅說:我知道路,左走一百米就到了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章