六、函數的基本使用

一、認識函數

1 什麼是函數
    函數就是具備某一功能的工具


2 爲什麼要用函數
    1  程序的組織結構不清晰,可讀性差
    2  代碼冗餘
    3  可擴展性差

3 如何用函數
    函數的使用必須遵循的原則:先定義,後調用
        修理工事先準備工具的過程即函數的定義
        修理工遇到應用場景拿來工具就用即函數的調用

    語法:
        def 函數名(參數1,參數2,...):
            """
            文檔註釋
            """
            code1
            code2
            code3
            ......
            return 返回值

        def:定義函數的關鍵字
        函數名: 就相當於一個變量名,指向函數的內存地址,
                注意:函數的內存地址()就可以出發函數體代碼的執行

        參數: 參數是函數的調用者爲函數體代碼傳值的媒介,在python中函數的參數無需聲明類型
        """文檔註釋""" : 推薦寫上
        代碼塊:就是函數體功能的具體實現
        return 返回值 :函數體代碼塊運行的成果


    函數的使用分爲兩個階段:
        定義階段: 只檢測語法,不執行代碼
        調用階段:運行函數體代碼
            def foo():
                xxx
                print(

# 先定義

def foo():
    print("from foo")

# 後調用

# 定義時無參,意味着調用時也無需傳入參數

print(foo)
foo()

# 先定義

def bar(x,y):
    print(x)
    print(y)

# 後調用

# 定義時無參,意味着調用時也必須傳入參數

bar('a',2)

# 定義無參函數:當函數體的代碼邏輯不依賴任何傳入的值就能執行,就不需要定義參數

def print_msg():
    print('='*50)
    print('welecome.....'.center(50,' '))
    print('='*50)
print_msg()
print_msg()
-----------------------------------------------------------------
==================================================
                  welecome.....                   
==================================================
==================================================
                  welecome.....                   
==================================================

#定義有參函數:當函數體的代碼邏輯依賴於外部調用者傳入的值才能執行,必須定義參數用來接收外部傳入的值

def max2(x,y):
    # x=1
    # y=3
    if x > y:
        print(x)
    else:
        print(y)
max2(1,4)
---------------------------------
4

# 定義階段

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

# 調用階段

foo()

# 定義階段

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

# 調用階段

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

二、定義函數的三種形式

1 無參函數

def foo():
    print('from foo')
foo()

2 有參函數

def bar(x,y):
    print(x,y)
bar(1,2)

3 空函數

def func():
    pass

三、調用函數的三種形式

1 #語句形式

def foo():
    print('from foo')
foo()

2 表達式形式

def foo(x,y):
    res = x + y
    return res

res=foo(1,2) #表達式形式
res1=foo(1,2)*100
print(res1)

3 可以當作參數傳給另外一個函數

def max2(x,y):
    if x > y:
        return x
    else:
        return y
res=max2(max2(1,2),3)
print(res)

四、函數的返回值

#一 函數的返回值需要注意:
#1 返回值沒有類型限制
#2 返回值沒有個數限制
#  返回1個值:調用函數拿到的結果就是一個值
#  返回多個值:調用函數拿到的結果就是一個元組
#  返回0個值,或者不寫return:調用函數拿到的結果就是None

#二 return關鍵字:return是函數結束的標誌,函數內可以有多個return,但只要執行一次,整個函數就結束

def f1():
    print('first')
    return 1
    print('second')
    return 2
    print('third')
    return 3
res=f1()
print(res)
----------------------------------------
first
1

def foo():
    count=1
    while True:
        print(count)
        if count == 3:
            return
        count+=1
foo()
------------------------------------------------------
1
2
3

def bar():
    pass
def foo():
    return [1,2],1,1.3,{'x':1},bar
res=foo()
print(res)
----------------------------------------------------------------
([1, 2], 1, 1.3, {'x': 1}, <function bar at 0x000002478D872EA0>)

def func():
    print('from foo')
    # return

res=func()
print(res)
----------------------------------------------------------------------------
from foo
None

五、函數參數的使用

#函數的參數分爲兩大類:
#1 形參: 指的是在定義函數階段括號內指定變量名,即形參本質就是"變量名"

#2 實參: 指的是在調用函數階段括號內傳入的值,即實參本質就是"值"

# 形參與實參的關係:在調用函數時,會將實參(值)賦值(綁定)給形參(變量名),
# 這種綁定關係在函數調用時臨時生效,在調用結束後就失效了

def foo(x,y): # x=1 y=2
    # x=1
    # y=2
    print(x,y)
foo(1,2)

# 形參與實參的具體分類
# 一 位置參數
# 1.1 位置形參: 在定義函數階段按照從左到右的順序依次定義的形參,稱之爲位置形參
# 注意:但凡按照位置定義的形參,必須被傳值,多一個不行,少一個也不行(一一對應)

def foo(x,y):
    print(x,y)
foo(1,2)

# 1.2 位置實參: 在調用函數階段按照從左到右的順序依次傳入的值,稱之爲位置實參
# 注意:但凡按照位置定義的實參,會與形參一一對應

二 關鍵字參數
#關鍵字實參: 在調用函數階段,按照key=value的形式指名道姓地爲形參傳值
#注意:
#1. 可以完全打亂順序,但仍然能指名道姓爲指定的形參傳值
#2. 可以混合使用位置實參與關鍵字實參,但是必須注意:
#    2.1 位置實參必須放到關鍵字實參前面
#    2.2 不能對一個形參重複賦值

def foo(name,age):
    print(name,age)
foo('egon',18)
foo(18,'egon')
foo(age=18,name='egon')
foo('egon',age=18)

# 三 默認參數
#默認參數:指的是在定義函數階段,就已經爲某個形參賦值了,改形參稱之爲有默認值的形參,簡稱默認形參
#注意:
#1. 在定義階段就已經被賦值,意味着在調用階段可以不用爲其賦值
#2. 位置形參應該放到默認形參前面
#3. 默認參數的值在函數定義階段就已經固定死了
#4. 默認參數的值通常應該是不可變類型

def foo(x,y=2):
    print(x,y)
foo(1)
foo(1,3)
foo(y=3,x=1)
----------------------------
1 2
1 3
1 3

-

m=10              ## 必須要放在上面纔可以被賦值到
def foo(x,y=m):
    print(x,y)

m=20                 #定義時不能定義在函數後面,否則會報 m 沒有定義
foo(1)
-------------------------
1 10
def register(name,hobby,l=[]):
    l.append(hobby)
    print('%s 的愛好爲 %s' %(name,l))

register('yxx','不洗澡')
register('egon','read')
-----------------------------
yxx 的愛好爲 ['不洗澡']
egon 的愛好爲 ['不洗澡', 'read']

def register(name, hobby, l=None):
    if l is None:
        l=[]
    l.append(hobby)
    print('%s 的愛好爲 %s' % (name, l))

register('yxx', '不洗澡',[])
register('egon', 'read',[])
--------------------------------------------------
yxx 的愛好爲 ['不洗澡']
egon 的愛好爲 ['read']

# 位置形參vs默認形參
# 對於大多情況下傳的值都不相同的,應該定義成位置形參
# 對於大多情況下傳的值都相同的,應該定義成默認形參

def register(name,age,sex='男'):
    print(name,age,sex)
register('李鐵蛋',18,)
register('劉二丫',19,'女')

# 四 可變長度的參數
# 站在實參的角度,參數長度可變指的是在調用函數時,傳入的實參值的個數不固定
#而實參的定義方式無法兩種:位置實參,關鍵字實參,對應着形參也必須有兩種解決方案*與**,類分別應對溢出的位置實參與關鍵字實參
 
#1. 在形參中帶*:會將調用函數時溢出位置實參保存成元組的形式,然後賦值*後的變量名

def foo(x,y,*z): #z=(3,4,5,6)
    print(x,y,z)
foo(1,2,3,4,5,6)

# 2. 在實參中帶*: 但凡在實參中帶*星的,在傳值前都先將其打散成位置實參,再進行賦值

def foo(x,y,*z): #z=(3,4,5,6)
    print(x,y,z)
foo(1,*[2,3,4,5,6]) # foo(1,2,3,4,5,6)
#
def foo(x,y,z):
    print(x,y,z)
foo(*(1,2,3)) #foo(1,2,3)
foo(*'abc')  #foo('a','b','c')

# 3. 在形參中帶**:會將調用函數時溢出關鍵字實參保存成字典的形式,然後賦值**後的變量名

def foo(x,y,**z): #z={'z':3,'a':1,'b':2}
    print(x,y,z)
foo(1,y=2,a=1,b=2,c=3)
foo(1,2,**{"r":4,'g':9}) # 正確的
------------------------------------------
1 2 {'a': 1, 'b': 2, 'c': 3}
1 2 {'r': 4, 'g': 9}
# 錯誤方式:
# foo(1,2,{"r":4,'g':9})  # 錯誤的  #不能直接接收以字典的形式,可以是以關鍵字傳入例如:(a=1,b=2),或是將字典的形式打散 例如: **{"a":1,'b':2}

# 4. 在實參中帶**: 但凡在實參中帶**星的,在傳值前都先將其打散成關鍵字實參,再進行賦值

def foo(x,y,**z): #z={'a':100,'b':200}
    print(x,y,z)
foo(1,**{'a':100,'b':200,'y':111}) #foo(1,b=200,a=100,y=111)
---------------------------
1 111 {'a': 100, 'b': 200}

def foo(x,y,z):
    print(x,y,z)
foo(**{'y':111,'x':222,'z':333}) #foo(z=333,x=222,y=111)
------------------------------------
222 111 333

#5. 規範: 在形參中帶*與**的,*後的變量名應該爲args,**後跟的變量名應該時kwargs

def foo(*args,**kwargs): #args=(1,2,3,4,5) kwargs={'a':1,'b':2,'c':3}
    print(args)
    print(kwargs)
foo(1,2,3,4,5,a=1,b=2,c=3)
------------------------------------
(1, 2, 3, 4, 5)
{'a': 1, 'b': 2, 'c': 3}

注意:

!!!!!!!!!!!當我們想要將傳給一個函數的參數格式原方不動地轉嫁給其內部的一個函數,應該使用下面這種形式

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

def wrapper(*args,**kwargs): #args=(1,2) kwargs={'z':3}
    bar(*args,**kwargs)
    #bar(*(1,2),**{'z':3})  #bar(1,2,z=3)
wrapper(1,2,z=3) # 雖然調用的是wrapper,但是要遵循的確是bar的參數標準
---------------------------------
1 2 3

五 命名關鍵字參數: 放到*與**之間的參數稱之爲命名關鍵字參數
# 注意: 命名關鍵字參數必須按照key=value的形式傳值

def foo(x,y,*args,m,n,**kwargs): #args=(3,4,5,6,7,8)
    print(x,y) # 1,2
    print(args) #(3,4,5,6,7,8)
    print(m,n) #222,333
    print(kwargs)
foo(1,2,3,4,5,6,7,8,n=333,m=222,a=1,b=2)
--------------------------------
1 2
(3, 4, 5, 6, 7, 8)
222 333
{'a': 1, 'b': 2}

def foo(*,x=1,y):
    print(x)
    print(y)
foo(y=2222,x=1111)
foo(y=2222)
-----------------------------------
1111
2222
1
2222

def foo(x,y=1,*args,m,**kwargs):
    print(x)
    print(y)
    print(args)
    print(m)
    print(kwargs)
foo('from x',ars='tuple',m='from m',kw='from kw',ar='args')
-----------------------------------------
from x
1
()
from m
{'ars': 'tuple', 'kw': 'from kw', 'ar': 'args'}

作業:

默寫:
    函數中參數的分類 及其作用  位置 關鍵字  形參 實參 可變長度參數
分類:形參,實參
作用:
位置:位置形參,位置實參
關鍵字:關鍵字實參: 在調用函數階段,按照key=value的形式指名道姓地爲形參傳值

形參:指的是在定義函數階段括號內指定變量名,即形參本質就是"變量名"
實參:指的是在調用函數階段括號內傳入的值,即實參本質就是"值"
可變長度參數:
站在實參的角度,參數長度可變指的是在調用函數時,傳入的實參值的個數不固定,而實參的定義方式無法兩種:位置實參,關鍵字實參,對應着形參也必須有兩種解決方案*與**,類分別應對溢出的位置實參與關鍵字實參

練習題:
    1.使用函數新的知識點繼續完善,優化購物車

    2.使用函數完成以下功能,數據格式如下
    [
        {“name”:”張無忌”,”number”,”sh01”,”math”:90,”english”:87,”chinese”:56},
        {“name”:”武則天”,”number”,”sh02”,”math”:40,”english”:97,”chinese”:67}....

    ]
    提供以下功能函數
        獲取指定學生的成績
        獲取指定學號的成績
        根據學生的學號修改姓名
        根據姓名修改指定學科的成績
        刪除指定學生及其成績

    3.博客作業 http://www.cnblogs.com/linhaifeng/articles/7531972.html#_label5

拓展:
    ATM 參考博客






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章