1. 程式人生 > >我的Python成長之路---Day10-函式的基本使用

我的Python成長之路---Day10-函式的基本使用

一、函式的使用原則

函式的使用應該分為兩個明確的階段
1. 定義階段:只檢測語法,不執行函式體程式碼
def func():
    print('from func')
2. 呼叫階段:會觸發函式體程式碼的執行
func()

函式使用的原則: 先定義後呼叫

示範一
def foo():
    print('from foo')
    bar()                     bar函式在這裡不能直接呼叫,違背了函式使用的原則,呼叫階段程式會進行報錯
foo()

# 示範二:
def bar():
    print('from bar')

def foo():
    print('from foo')
    bar()                      在這裡程式會正常執行,bar函式在被foo呼叫之前已經被定義過了

foo()

# 示範三:
def foo():                    示範三裡面雖然bar函式定義在後面,但是函式定義階段是隻檢測語法不執行程式碼的,在語法上並沒有錯誤,所                                     以在呼叫foo函式的時候,bar函式已經定義好了,在foo函式內再呼叫也不會出現錯誤
    print('from foo')
    bar()

def bar():
    print('from bar')

foo()

示範四:
def foo():
    print('from foo')
    bar()

foo()                            示範四就會進行報錯了,在呼叫foo的時候,bar函式還沒有定義完成

def bar():
    print('from bar')

二、函式的定義三種形式

 有參函式
def func(x):
    pass

func(1)

無參函式
def bar():
    pass

bar()
空函式
def func():
    pass

def auth():
    pass


三、函式呼叫的三種形式

register() # 語句形式

def max2(x,y):
    if x > y:
        return x
    else:
        return y

res=max2(10,20)*12 # 表示式形式

res=max2(max2(10,20),30) # 將函式的呼叫當作引數傳給另外一個函式
print(res)

四、函式的返回值(return)的使用

return 值:
注意點:
1. 函式的返回值沒有型別限制
2. 函式的返回值沒有個數限制
2.1 返回多個值: 多個返回值用逗號分隔開,返回的是元組形式

def func():
    print('from func')
    return 1,1.1,'hello',[1,2,3]

res=func()
print(res,type(res))        輸出為:(1, 1.1, 'hello', [1, 2, 3]) <class 'tuple'>


2.2 返回1個值: 返回的就是該值本身

def func():
    return 123
res=func()
print(res,type(res))           輸出:123 <class 'int'>

2.3 返回0個值或者乾脆沒有return: 返回None

def func():
    return
    pass
res=func()
print(res)           輸出:None

return除了有返回值的功能,還有結束函式執行的的功能
函式內可以有多個return,但只要執行一次,整個函式就立即結束,並且將return後的值返回

def func():
    print(1)                  
    return                            在呼叫函式的時候,在執行到return時真個函式就會立即結束,並將return的值返回
    print(2)
    return
    print(3)

func()

五、函式引數的使用

一: 函式的引數分為兩大類:
形式引數(形參): 在定義函式階段,括號內定義的引數/變數名稱為形參
實際引數(實參): 在呼叫函式階段,括號內傳入的值/變數值稱為實參
ps: 在呼叫函式階段會將實參(值)的值繫結給形參(變數名),這種繫結關係只在呼叫函式時生效,在函式執行完畢後就會解除繫結
def func(x,y): #x=1 y=2
    # x=1       (定義引數時,相當於在這裡加上了兩行變數的定義)
    # y=2
    print(x,y)

func(1,2)

print(x)
print(y)

二: 細分:
1. 位置引數:(位置形參和位置實參)
1.1 位置形參: 在定義階段,按照從左到右的順序依次定義的形參稱之為位置形參
特點: 但凡是按照位置定義的形參,必須被傳值,多一個不行少一個也不行
def func(x,y,z):
    print(x,y,z)

func(1,2)            呼叫時程式會報錯
func(1,2,3)
func(1,2,3,4)     呼叫時程式會報錯

1.2 位置實參: 在呼叫階段,按照從左到右的順序依次傳入的值稱之為位置實參
特點:
1. 與形參一一對應
def func(x,y,z):
    print(x,y,z)

func(2,1,3)2. 關鍵字實參: 在呼叫階段,按照key=value的形式定義的實參稱之為關鍵字實參
特點: 可以完全打亂順序,但仍然能為指定的形參傳值(總結:指名道姓地為指定的形參傳值)

def func(x,y,z):
    print(x,y,z)

func(x=1,y=2,z=3)
func(1,2,3)
func(z=3,y=2,x=1)


實參的形式可以是位置實參與關鍵字實參混合使用,但是必須遵循原則
1.位置實參必須放在關鍵字實參的前面
2.不能對同一個形參重複傳值
func(1,z=3,y=2)
func(z=3,1,y=2)          #錯誤
func(1,z=3,x=2,y=3)   #錯誤

3. 預設形參:在定義階段,就已經為形參賦值,該形參稱之為預設形參
特點
1. 定義階段就已經有值, 意味著呼叫階段可以不用傳值

def register(name,age,sex='male'):
    print(name,age,sex)

register('egon',18,)               在這裡前四個都使用預設的sex值就可以,呼叫函式的時候,不需要再給 
                                   sex賦值,減少呼叫時的麻煩
register('lxx',38,)
register('cw',48,)
register('yyh',58,)
register('alex',73,'female')       在需要改變sex的值時,重新給一個值就可以了

def func(x,y,z=100):
    print(x,y,z)

func(10,20)
func(10,20,200)


2. 位置形參必須放到預設形參的前面

def func(x,z=100,y):      這樣的位置程式會進行報錯,將預設形參放到位置形參後邊即可解決
    print(x,y,z)


3. 預設形參的值在函式定義階段就已經固定死了,定義階段之後的改動不會影響該值

m=10
def func(x,y,z=m):
    #z=10
    print(x,y,z)
m=100                   在這裡再改變m的值不會對函式中m的使用產生影響
func(1,2)


4. 預設形參的值通常應該是不可變型別

 

def add_hobby(name,x,hobbies=[]):
    hobbies.append(x)
    print('%s 的愛好有 %s' %(name,hobbies))

add_hobby('egon','read',)     輸出結果:egon 的愛好有 ['read']
add_hobby('wxx','eat',)               wxx 的愛好有 ['read', 'eat']
add_hobby('alex','piao')              alex 的愛好有 ['read', 'eat', 'piao']   有這樣的結果是因為,在初始時,hobbies裡邊是一個空列表,寫入第一個egon的愛好進去之後,就變成了['read'],再呼叫函式時,hobies就變成了預設形參,hobbies=['read'],這時再使用.append將'eat'加入進去時,就變成了['read','eat']
 

def add_hobby(name,x,hobbies=None):   解決方案
    if hobbies is None:
        hobbies=[]
    hobbies.append(x)
    prinvt('%s 的愛好有 %s' %(name,hobbies))

4. 可變長引數:
可變長實參:指的是在呼叫階段,實參值個數是不固定的,
實參無非兩種形式(位置,關鍵字實參),對應著形參也必須有兩種解決方案來分別接收溢位位置實參或者關鍵字實參
*--->溢位的位置實參
**--->溢位的關鍵字實參

def sum2(*x): #x=(1,2,3,4,5)
    res=0
    for i in x:
        res+=i
    return res
print(sum2(1,2,3,4,5))

4.1 *的用法
在形參前加*:*會將溢位的位置實參存成元組的形式,然後賦值給*後的形參名
def func(x,y,*z): #z=(3,4,5)
    print(x,y,z)
func(1,2,3,4,5)

在實參前加*但凡碰到實參中帶*的,先將實參打散成位置實參再與形參做對應
def func(x,y,z):
    print(x,y,z)
func(1,2,[3,4,5])
func(*[1,2,3,4,5]) #func(1,2,3,4,5)   在這裡執行'打散'操作
func(*[1,2,3]) #func(1,2,3)

def func(x,y,*z):
    print(x,y,z)

func(1111,2222,*[1,2,3,4,5]) #func(1111,2222,1,2,3,4,5)

4.2 **的用法
在形參前加**:**會將溢位的關鍵字實參存成字典的形式,然後賦值給**後的形參名
def func(x,y,**z): #z={'c':3,'b':2,'a':1}
    print(x,y,z)
func(1,y=2,a=1,b=2,c=3)

在實參前加**:但凡碰到實參中帶**的,先將實參打散成關鍵字實參再與形參做對應
def func(x,y,z):
    print(x,y,z)

func(1,**{'y':2,'z':3})                #func(1,z=3,y=2)
func(1,**{'a':2,'y':333,'z':3})    #func(1,a=2,y=333,z=3) # 錯誤

def func(x,y,**z):
    print(x,y,z)

func(**{'y':1,'x':2,'a':1111,'b':2222}) #func(y=1,x=2,a=1111,b=2222)

形參中:*args,**kwargs
def func(x,*args):
    print(x)
    print(args)

def func(x,**kwargs):
    print(x)
    print(kwargs)

*與**的應用:
def index(name,age,sex):
    print('index=====>',name,age,sex)

會將wrapper函式接收的引數格式原封不動地轉嫁給其內部的index函式,必須要遵循的是index的引數規則

這時*args和**kwargs可以接受任意型別的值
def wrapper(*args,**kwargs):       #args=('egon',) kwargs={'sex':'male','age':18}
    print(args)
    print(kwargs) 
    index(*args,**kwargs)              #index(*('egon',),**{'sex':'male','age':18}) #index('egon',sex='male',age=18)

wrapper(1,2,3,4,5,a=1,b=2,c=3)
wrapper('egon',sex='male',age=18)