【Python基礎(chǔ)】13. 函數(shù) Function

這篇筆記記錄的知識(shí)點(diǎn):

  • 函數(shù)的基本概念
  • 自定義函數(shù)
  • 函數(shù)的幾種參數(shù)

編程的三種方式:
1.OOP 面向?qū)ο缶幊蹋f物皆對(duì)象熊楼,以class為主,抽象化
2.POP 面向過程編程,萬事皆過程驼侠,def定義過程
3.函數(shù)式編程,將某種功能封裝起來谆吴,用的時(shí)候直接調(diào)用函數(shù)名倒源,def定義函數(shù),也叫function/方法/過程/子程序

</br>

函數(shù)的基礎(chǔ)概念:

  • 函數(shù)是一種設(shè)計(jì)工具,它能讓程序員將復(fù)雜的系統(tǒng)分解成可管理的部件, 用于將相關(guān)功能打包并參數(shù)化
  • 一組語句的集合通過一個(gè)名字(函數(shù)名)封裝起來句狼,要想執(zhí)行這個(gè)函數(shù)笋熬,只需要調(diào)用其函數(shù)名即可
  • 可以理解為是一個(gè)帶有名字的,具有一定功能的,用于完成具體工作的代碼塊.
  • 當(dāng)程序需要多次執(zhí)行同一個(gè)任務(wù)時(shí),只需要調(diào)用具有該功能的函數(shù)即可.
  • 函數(shù)特性:
    • 代碼重用
    • 保持一致性
    • 可擴(kuò)展性
  • Python的函數(shù)可以分為兩類:

    1. 內(nèi)置函數(shù):
      python內(nèi)置了一系列的常用函數(shù),以便于使用. 我們可以根據(jù)不同的功能需求直接調(diào)用使用.

      內(nèi)置函數(shù).png

    2. 自定義函數(shù):
      我們自己根據(jù)功能需求,以固定的語句格式定義的函數(shù).

    3. 空函數(shù)

    pass語句什么都不做.
    實(shí)際上pass是用來作為占位符腻菇,比如現(xiàn)在還沒想好怎么寫函數(shù)的代碼胳螟,就可以先放一個(gè)pass,讓代碼能運(yùn)行起來筹吐。

    def func1():
       pass
    
  • 常見的幾種函數(shù):
    1. 全局函數(shù) (定義在模塊中,僅限單個(gè)文件)
    2. 局部函數(shù)(嵌套于其他函數(shù)中)
    3. lambda函數(shù)(匿名函數(shù))
    4. 內(nèi)置函數(shù)

</br>

自定義函數(shù)

定義函數(shù)的格式:

python定義函數(shù)使用def關(guān)鍵字糖耸,一般格式如下:

def 函數(shù)名(參數(shù)):
    '''文檔字串符(docstring),注釋,描述該函數(shù)是做什么的'''
    函數(shù)體(代碼行)         #這個(gè)函數(shù)要實(shí)現(xiàn)的功能代碼

函數(shù)名的命名規(guī)則:

  • 函數(shù)名必須以下劃線或字母開頭,可以包含任意字母丘薛、數(shù)字或下劃線的組合嘉竟。不能使用任何的標(biāo)點(diǎn)符號(hào);
  • 函數(shù)名是區(qū)分大小寫的。
  • 函數(shù)名不能是保留字(關(guān)鍵字)

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

定義了函數(shù)之后周拐,就相當(dāng)于有了一個(gè)具有某些功能的代碼
但是,函數(shù)是不會(huì)自動(dòng)執(zhí)行的,想要讓這些代碼能夠執(zhí)行铡俐,需要調(diào)用它
調(diào)用函數(shù)很簡(jiǎn)單的,通過 函數(shù)名()即可完成調(diào)用:

def test1():                    # 定義函數(shù)名
    print("hello!")             # 定義函數(shù)的功能
    
test1()                         # 調(diào)用函數(shù)

函數(shù)的文檔說明
文檔字串符(docstring)描述該函數(shù)是做什么的,盡量給自定義函數(shù)備注,方便日后查看使用.

def test(a,b):
 '''用來完成對(duì)2個(gè)數(shù)求和'''
     print("%d" % (a+b))

test(11,22)

如果執(zhí)行妥粟,以下代碼:

help(test)

能夠看到test函數(shù)的相關(guān)說明:

Help on function test in module __main__:

test(a, b)
    用來完成對(duì)2個(gè)數(shù)求和
(END)

Tips: 使用三引號(hào)來構(gòu)成文檔字符串审丘,用來解釋該函數(shù)的主要功能,這是一個(gè)很好的編碼習(xí)慣.

</br>

函數(shù)的參數(shù)

實(shí)參和形參

實(shí)參是一個(gè)實(shí)實(shí)在在存在的參數(shù)勾给,是實(shí)際占用內(nèi)存地址的
形參只是意義上的一種參數(shù)滩报,在定義的時(shí)候是不占內(nèi)存地址的.

  • 定義時(shí)小括號(hào)中的參數(shù),用來接收參數(shù)用的播急,稱為 “形參”
  • 調(diào)用時(shí)小括號(hào)中的參數(shù)脓钾,用來傳遞給函數(shù)用的,稱為 “實(shí)參”

形參:形式參數(shù)桩警,不是實(shí)際存在可训,是虛擬變量,在定義函數(shù)和函數(shù)體的時(shí)候使用形參捶枢,目的就是在函數(shù)調(diào)用的時(shí)候接收實(shí)參(實(shí)參個(gè)數(shù)握截,類型應(yīng)與實(shí)參一一對(duì)應(yīng))

實(shí)參:實(shí)際參數(shù),調(diào)用函數(shù)時(shí)候傳給函數(shù)的變量烂叔,可以是常量谨胞,變量,表達(dá)式蒜鸡,函數(shù)胯努,傳給形參

區(qū)別:形參是虛擬的,不占用內(nèi)存空間逢防,形參變量只有在調(diào)用時(shí)才分配內(nèi)存單元叶沛,實(shí)參是一個(gè)變量,占用空間忘朝,數(shù)據(jù)傳送單向灰署,實(shí)參傳給形參,不能形參傳給實(shí)參辜伟。

def sum_num(a,b):        #a,b 是形參
    sum_num = a+b
    print(sum_num)
    
sum_num(10,33)           #10,33 是實(shí)參

定義時(shí)小括號(hào)中的參數(shù)氓侧,用來接收參數(shù)用的脊另,稱為 “形參”
調(diào)用時(shí)小括號(hào)中的參數(shù)导狡,用來傳遞給函數(shù)用的,稱為 “實(shí)參”
沒特別指明偎痛,形參和實(shí)參必須一一對(duì)應(yīng)旱捧,多一個(gè)少一個(gè)都報(bào)錯(cuò)

</br>

常用的幾種參數(shù)類型:

在Python中可以使用必選參數(shù),默認(rèn)參數(shù),可變參數(shù)枚赡,關(guān)鍵字參數(shù)氓癌,這四類可以一起使用,或者只使用其中某一些.
但是有多種參數(shù),在定義函數(shù)和傳參的時(shí)候,必須要注意參數(shù)的置放順序:
參數(shù)的順序必須是:

<h6 align = "center" >必備參數(shù)贫橙,可變(不定長(zhǎng))參數(shù)*args, 默認(rèn)(缺省)參數(shù)贪婉,可變(不定長(zhǎng))參數(shù)**kargs,關(guān)鍵字參數(shù) </h6>

1. 必備參數(shù)(位置參數(shù))

  • 調(diào)用函數(shù)時(shí)根據(jù)函數(shù)定義的參數(shù)位置來傳遞參數(shù)卢肃。
  • 所有參數(shù)的順序必須一一對(duì)應(yīng)疲迂,且少一個(gè)參數(shù)都不可以
def func_1(name,sex):
    sex_dict = {1: u'先生', 2: u'女士'}
    print ('hello %s %s, welcome to python world!' %(name, sex_dict.get(sex, u'先生')))
func_1("劉",2)

運(yùn)行結(jié)果:hello 劉 女士, welcome to python world!

2. 默認(rèn)參數(shù)(缺省參數(shù))

  • 在形參中默認(rèn)有值的參數(shù)
  • python為了簡(jiǎn)化函數(shù)的調(diào)用,提供了默認(rèn)參數(shù)機(jī)制
  • 用于定義函數(shù)莫湘,為參數(shù)提供默認(rèn)值尤蒿,調(diào)用函數(shù)時(shí)可傳可不傳該默認(rèn)參數(shù)的值(注意:所有位置參數(shù)必須出現(xiàn)在默認(rèn)參數(shù)前,包括函數(shù)定義和調(diào)用)
  • 在定義有默認(rèn)參數(shù)的函數(shù)時(shí)幅垮,需要注意以下:
    • 必選參數(shù)必須在前面腰池,默認(rèn)參數(shù)在后;
    • 設(shè)置何種參數(shù)為默認(rèn)參數(shù)忙芒?一般來說示弓,將參數(shù)值變化小的設(shè)置為默認(rèn)參數(shù)。
def func_2(name,age=18):
    print("我是位置參數(shù):%s"%name,"我是默認(rèn)參數(shù):%s"%age)

func_2("如花")   #只給name傳參,會(huì)調(diào)用默認(rèn)參數(shù)的值
func_2("如花",28)  #給age傳參,會(huì)覆蓋之前的默認(rèn)參數(shù)

運(yùn)行結(jié)果如下:

我是位置參數(shù):如花 我是默認(rèn)參數(shù):18
我是位置參數(shù):如花 我是默認(rèn)參數(shù):28

3. 可變參數(shù)(不定長(zhǎng)參數(shù))

  • 也叫做不定長(zhǎng)參數(shù),動(dòng)態(tài)參數(shù)
  • 定義函數(shù)時(shí)匕争,有時(shí)候我們不確定調(diào)用的時(shí)候會(huì)傳遞多少個(gè)參數(shù)(不傳參也可以)避乏。此時(shí),可用包裹(packing)位置參數(shù)*args甘桑,或者包裹關(guān)鍵字參數(shù)**kargs拍皮,來進(jìn)行參數(shù)傳遞,會(huì)顯得非常方便跑杭。
  • 有時(shí)可能需要一個(gè)函數(shù)能處理比當(dāng)初聲明時(shí)更多的參數(shù), 這些可變參數(shù)也被叫做不定長(zhǎng)參數(shù)铆帽,聲明時(shí)不會(huì)命名。
    • 加了星號(hào)(*)的變量args會(huì)存放所有未命名的變量參數(shù)德谅,args為元組
    • 而加**的變量kwargs會(huì)存放命名參數(shù)爹橱,即形如key=value的參數(shù), kwargs為字典

(1) 包裹位置傳遞*args
我們傳進(jìn)的所有參數(shù)都會(huì)被args變量收集窄做,它會(huì)根據(jù)傳進(jìn)參數(shù)的位置合并為一個(gè)元組(tuple)愧驱,args是元組類型,這就是包裹位置傳遞椭盏。

def func(*args):
    ....
    
# func()
# func(a)
# func(a, b, c)

(2)包裹關(guān)鍵字傳遞**kargs
kargs是一個(gè)字典(dict)组砚,收集所有關(guān)鍵字參數(shù)

def func(**kargs):
    ....

# func(a=1)
# func(a=1, b=2, c=3)

(3) 對(duì)于*args**kwargs在函數(shù)中我們可以稱之為參數(shù)組,但是這兩個(gè)還是有區(qū)別的

1:args的功能:------接收N個(gè)位置參數(shù)掏颊,轉(zhuǎn)換成元組tuple形式
2:
kwargs的功能------接收N個(gè)關(guān)鍵字參數(shù)糟红,轉(zhuǎn)換成字典dict形式
3:位置參數(shù)一定要在關(guān)鍵字參數(shù)之前艾帐,也就是(
args,**kwargs)

(4) *args**kwargs一起用, 功能會(huì)更強(qiáng)大
可以兩個(gè)一起使用:功能更加的強(qiáng)大:會(huì)把無參數(shù)名臣的封裝成一個(gè)tuple 把有參數(shù)名稱的封裝成一個(gè)字典盆偿;并且柒爸,arg必須在**kwargs前面

# def show(*args ,**kwargs):
#     print(args,kwargs)
# show(11,22,33,nn=22,kk=33)

值得注意的是雖然*args**kwargs會(huì)把我們給他的參數(shù)封裝成列表和字典,但是如果我們?cè)诮o定實(shí)際參數(shù)的時(shí)候給的是一個(gè)列表或者是字典事扭,只是表示只有一個(gè)實(shí)參捎稚,而不是列表和字典里面的值;如果想要實(shí)現(xiàn)這個(gè)功能求橄,那么我們就需要在列表或者字典前面加上*或者**就能實(shí)現(xiàn)了阳藻;

4. 關(guān)鍵字參數(shù)

用于函數(shù)調(diào)用,通過“鍵-值”形式加以指定谈撒⌒饶啵可以讓函數(shù)更加清晰、容易使用啃匿,同時(shí)也清除了參數(shù)的順序需求蛔外。

#以下是用關(guān)鍵字參數(shù)正確調(diào)用函數(shù)的實(shí)例 
func_01('tanggu', sex=1)
func_01(1, name='tanggu')
func_01(name='tanggu', sex=1)
func_01(sex=1, name='tanggu')

# 以下是錯(cuò)誤的調(diào)用方式
func_01(name='tanggu', 1)
func_01(sex=1, 'tanggu')

tips:雖然函數(shù)參數(shù)類型很多,但不要同時(shí)使用太多的組合溯乒,否則函數(shù)接口的可理解性很差.

</br>

函數(shù)的返回值

函數(shù)的返回值是函數(shù)重要的組成部分夹厌。函數(shù)的根本在于實(shí)現(xiàn)程序的部分功能,所以很多時(shí)候我們需要將函數(shù)執(zhí)行后的結(jié)果返回給程序再由程序作出進(jìn)一步的操作裆悄∶疲可以說是函數(shù)的返回值令函數(shù)與函數(shù)之間,函數(shù)與主程序之間更加緊密的聯(lián)系起來光稼。

函數(shù)的返回值:

  • 在Python的函數(shù)中都有一個(gè)返回值或南,默認(rèn)為None。也可以使用return value語句來定義一個(gè)且只能定義一個(gè)可為任意類型的返回值艾君。但是我們能夠返回一個(gè)序列類型的對(duì)象采够,來實(shí)現(xiàn)返回多個(gè)值的效果。
  • 函數(shù)外部的代碼要想獲取函數(shù)的執(zhí)行結(jié)果冰垄,就可以在函數(shù)里面用return語句蹬癌,把結(jié)果返回.
  • return 代表一個(gè)函數(shù)的終止,函數(shù)在執(zhí)行過程中只要遇到return語句虹茶,就會(huì)停止執(zhí)行逝薪,并返回結(jié)果.如果return 后面帶一個(gè)print 或者return ,則后面的不執(zhí)行
  • 如果未在函數(shù)中指定return蝴罪,那么這個(gè)函數(shù)的返回值就是None
def func_2(name,age=18):
    print("我是位置參數(shù):%s"%name,"我是默認(rèn)參數(shù):%s"%age)


func_2("如花")   #只給name傳參
func_2("如花",28)  #給age傳參,會(huì)覆蓋之前的默認(rèn)參數(shù)


def without_return(a,b):  #定義一個(gè)沒有return的函數(shù)
    print(a+b)
    print(a-b)


def with_return(a,b):   #定義一個(gè)有return的函數(shù)
    return a+b
    return a-b

result1 = without_return(5,10)  #調(diào)用上邊定義的沒有return的函數(shù)
result2 = with_return(5,10)     #調(diào)運(yùn)上邊定義的有return的函數(shù)

print("沒有返回值的函數(shù):",result1)
print("有返回值的函數(shù):",result2)

上段代碼運(yùn)行后,結(jié)果如下:

15
-5
沒有返回值的函數(shù): None
有返回值的函數(shù): 15

[注意:]

  • 定義的函數(shù)沒有返回值,調(diào)用時(shí)接用變量收到的是None
  • 函數(shù)體里的代碼執(zhí)行完后會(huì)回到函數(shù)調(diào)用的地
  • 函數(shù)體里有多個(gè)return語法不會(huì)報(bào)錯(cuò),但是不能做到返回多個(gè)值的操作
  • 函數(shù)執(zhí)行到return語句表示函數(shù)執(zhí)行結(jié)束,后邊有再多也不會(huì)執(zhí)行了

接收多個(gè)rerun值

理論上,return只能返回一個(gè)值; 如果想要返回多個(gè)值,可以考慮把多個(gè)值放在列表,元祖,字典里邊.

def return_value():
    print('返回多個(gè)值')
    return [1,3,5]
    #return (1,3,5)
    #return {'a':1,'b':2,'c':3}

result = return_value()
print(result)

上述代碼運(yùn)行結(jié)果:

返回多個(gè)值
[1, 3, 5]
  • return后面可以是元組董济,列表、字典等洲炊,只要是能夠存儲(chǔ)多個(gè)數(shù)據(jù)的類型感局,就可以一次性返回多個(gè)數(shù)據(jù)
  • 如果return后面有多個(gè)數(shù)據(jù),那么默認(rèn)是元組

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

  • 函數(shù)的嵌套,在函數(shù)里邊再定義一個(gè)函數(shù)
  • 調(diào)用可以理解為,是在一個(gè)函數(shù)里調(diào)用了其他函數(shù)
  • 嵌套函數(shù)不能在外部使用,只能在函數(shù)內(nèi)部使用
def show_msg():
    print("show_msg")# 在函數(shù)里面定義的函數(shù)就是嵌套函數(shù)
    
    def show():   
        print("我是函數(shù)體里面的內(nèi)部函數(shù)->>子函數(shù)")
    
    show()       # 在函數(shù)體里面調(diào)用嵌套函數(shù)
 
show_msg()      # 調(diào)用函數(shù)
                # 注意點(diǎn): 嵌套函數(shù)不能再函數(shù)外使用暂衡,只能在函數(shù)內(nèi)部使用

上述代碼運(yùn)行結(jié)果:

show_msg
我是函數(shù)體里面的內(nèi)部函數(shù)->>子函數(shù)

函數(shù)嵌套的小應(yīng)用: 使用冰箱:

  • 在實(shí)際開發(fā)中,使用函數(shù)的嵌套可以大大的提高代碼的可讀性
def use_ice_box(eat):
    # 嵌套函數(shù)的作用询微,把函數(shù)拆分成不同的功能函數(shù)

    # 打開冰箱
    def open_ice_box():
        print("打開冰箱門")

    # 向冰箱放入食物
    def put_eat(eat):
        print("把%s放入冰箱" % eat)

    # 關(guān)閉冰箱
    def close_ice_box():
        print("關(guān)閉冰箱門")


    open_ice_box()
    put_eat(eat)
    close_ice_box()


use_ice_box("蘋果")

局部變量和全局變量,函數(shù)的作用域

變量作用域

LEGB原則

  • Python中,程序的變量并不是在哪個(gè)位置都可以訪問的狂巢,訪問權(quán)限決定于這個(gè)變量是在哪里賦值的撑毛。
  • 變量的作用域決定了在哪一部分程序可以訪問哪個(gè)特定的變量名稱。
  • Python的作用域一共有4種唧领,如下:
    • L ( Local):函數(shù)內(nèi)的區(qū)域藻雌,包括局部變量和形參。
    • E(Enclosing):外面嵌套函數(shù)區(qū)域斩个,常見的是閉包函數(shù)外的函數(shù)胯杭。
    • G( Global):全局作用域。
    • B( Built-in): 內(nèi)建作用域受啥。
  • Python中變量是采用L -> E->G一>B的規(guī)則查找
    • 當(dāng)Python檢索變量的時(shí)候做个,先是在局部中查找,如果找不到滚局,便會(huì)去局部外的局部找(例如閉包)居暖,再找不到就會(huì)去全局找,再者去內(nèi)中找藤肢。

局部變量

  • 局部變量太闺,就是在函數(shù)內(nèi)部定義的變量
  • 作用范圍:只能在函數(shù)體里面使用
  • 局部變量的作用: 臨時(shí)存儲(chǔ)函數(shù)體里面的所需要的數(shù)據(jù)的
    • 局部變量等函數(shù)執(zhí)行完成以后會(huì)釋放
    • 如果函數(shù)里面return了一個(gè)返回值,那么等外界使用完成以后該返回值以后才會(huì)釋放

全局變量和關(guān)鍵字global

  • 如果一個(gè)變量嘁圈,既能在一個(gè)函數(shù)中使用省骂,也能在其他的函數(shù)中使用,這樣的變量就是全局變量
  • 也可以理解成在函數(shù)外定義的變量就是全局變量
num1 = 1     #<--全局變量

def funcA():
    num1 = 3      #<--- 局部變量.可以理解為定義了一個(gè)局部變量最住,只不過局部變量的名字和全局變量的名字相同而已冀宴,不是同一個(gè)變量
    print("funcA里的變量:",num1)

def funcB():
    print("funcB里的變量:",num1) 

funcA()
funcB()

上述代碼運(yùn)行結(jié)果:

funcA里的變量: 3
funcB里的變量: 1

使用關(guān)鍵字global修改全局變量

當(dāng)內(nèi)部作用域想修改外部作用域的變量時(shí),要用到global和nonlocal關(guān)鍵字了温学。
global關(guān)鍵字用來在函數(shù)或其他局部作用域中使用全局變量略贮。但是如果不修改全局變量也可以不使用global關(guān)鍵字。

  • 如果在函數(shù)中出現(xiàn)global 全局變量名字, 那么這個(gè)函數(shù)中即使出現(xiàn)和全局變量名相同的變量名 = 數(shù)據(jù) 也理解為對(duì)全局變量進(jìn)行修改仗岖,而不是定義局部變量
  • global 表示聲明要修改全局變量
  • 如果在一個(gè)函數(shù)中需要對(duì)多個(gè)全局變量進(jìn)行修改逃延,那么可以使global a, b,...n
  • 也可以多次用global聲明,global a,global b
# 修改全局變
num1 = 1

def funcA():
    global num1    # <-- 表示聲明要修改全局變量
    num1 = 3
    print("funcA里的變量:",num1)

def funcB():
    print("funcB里的變量:",num1)

funcA()
funcB()

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

funcA里的變量: 3
funcB里的變量: 3

在Python中,以上邊代碼為例,如果在函數(shù)內(nèi)部對(duì)全局變量num1進(jìn)行修改轧拄, Python會(huì)把變量num1當(dāng)做是局部變量揽祥,為了使全局變量生效,我們可以在函數(shù)內(nèi)使用global關(guān)鍵字進(jìn)行聲明.
如果沒有對(duì)變量num1進(jìn)行全局變量申明檩电,運(yùn)行程序后會(huì)報(bào)錯(cuò):UnboundLocalError: local variable 'a' referenced before assignment

nonlocal關(guān)鍵字

nonlocal是在Python3.0中新增的關(guān)鍵字拄丰,python2.x不提供支持府树。
使用nonlocal關(guān)鍵字可以在一個(gè)嵌套的函數(shù)中修改嵌套作用域中的變量。
示例一:

def FinalResult():
    result = 0
    print("外部函數(shù)的變量result的值為:"+ str(result))

    def sumResult():
        result = 12
        print("內(nèi)部函數(shù)的變量result的值為"+str(result))
    sumResult()


FinalResult()

上述示例一代碼運(yùn)行結(jié)果如下:

外部函數(shù)的變量result的值為:0
內(nèi)部函數(shù)的變量result的值為12

示例二:

def FinalResult():
    result = 0
    #print("外部函數(shù)的變量result的值為:"+ str(result))

    def sumResult():
        result = 12
        print("內(nèi)部函數(shù)的變量result的值為"+str(result))

    sumResult()
    print("外部函數(shù)的變量result的值為:"+ str(result))


FinalResult()

上述示例二代碼運(yùn)行結(jié)果如下:

內(nèi)部函數(shù)的變量result的值為12
外部函數(shù)的變量result的值為:0

注意 通過上述示例可以看出, 嵌套在函數(shù)FinalResult內(nèi)部的內(nèi)嵌函數(shù)sumResult中, 我們對(duì)變量result的賦值,其實(shí)本質(zhì)是重新創(chuàng)建了一個(gè)新的變量,而不是外部函數(shù)FinalResultresult=0這條語句的重新賦值.
(2) 通過調(diào)換外部函數(shù)的print語句調(diào)用內(nèi)部函數(shù)sumResult兩條語句的先后位置, 可以對(duì)比發(fā)現(xiàn), 內(nèi)部函數(shù)的變量賦值,無論什么時(shí)候被調(diào)用都沒有對(duì)外部的同名變量造成影響.

示例三:

  • 使用nonlocal關(guān)鍵字
  • 在內(nèi)部嵌套的函數(shù)sumResult中使用了nonlocal關(guān)鍵字料按,就會(huì)告訴Python在外部的函數(shù)FinalResult中使用嵌套作用域中的變量result
  • 這樣,當(dāng)我們?cè)趦?nèi)嵌函數(shù)中對(duì)變量result進(jìn)行修改時(shí)奄侠,會(huì)直接影響到整個(gè)嵌套作用域中的result變量
def FinalResult():
    result = 0

    def sumResult():
        nonlocal result
        result = 12
        print("內(nèi)部函數(shù)的變量result的值為"+str(result))

    sumResult()
    print("外部函數(shù)的變量result的值為:"+ str(result))

FinalResult()

上述示例三代碼運(yùn)行結(jié)果如下:

內(nèi)部函數(shù)的變量result的值為12
外部函數(shù)的變量result的值為:12

注意

  • 使用global關(guān)鍵字修飾的變量之前可以不存在
  • 使用nonlocal關(guān)鍵字修飾的變量之前不存在,運(yùn)行會(huì)報(bào)錯(cuò):
    • SyntaxError: no binding for nonlocal 'result' found

[小總結(jié):]
一個(gè)變量在函數(shù)體外,一個(gè)變量在函數(shù)體內(nèi), 改變量用global.
一個(gè)變量在內(nèi)嵌函數(shù)里,一個(gè)變量在包裹內(nèi)嵌函數(shù)的外層函數(shù)里,改變量nonlocal

多層嵌套函數(shù)和函數(shù)外同用一個(gè)變量,用global申明.

(這段代碼為實(shí)驗(yàn),不確定全適用,也有可能方法有點(diǎn)蠢,因?yàn)楹髞戆l(fā)現(xiàn),貌似可以用return( ̄. ̄))

  • 申明變量的原則是,哪里用就在哪里申明.

假設(shè)我們有一個(gè)變量result,這個(gè)變量會(huì)在函數(shù)體外使用,也會(huì)在多層嵌套的函數(shù)的某幾個(gè)層里使用.
我們希望達(dá)到的效果是:在任何一個(gè)地方修改變量result,所有位置的變量result的值都改變,即在之后無論在函數(shù)外還是函數(shù)內(nèi)再調(diào)用這個(gè)變量result,得到的是最新的result的值.具體實(shí)現(xiàn)如下:

示例四:

result = 10     # <== 函數(shù)外的變量result
print("函數(shù)外的result變量:"+str(result))     #<== 第一條print執(zhí)行語句

def FinalResult():
    global result    <== 申明result為全局變量, 這里如果不申明, 知result程序默認(rèn)不是同一個(gè)變量,只是同名.
    result = 11

    print("外部函數(shù)的變量result的值為:"+ str(result))    # <== 第2條print執(zhí)行語句
    def sumResult():
       #nonlocal resul     # <== 這里如果用nonlocal,會(huì)報(bào)錯(cuò)
        global result   #用global申明result為全局變量
        result = 12
        print("內(nèi)部函數(shù)的變量result的值為"+str(result))     # <== 第3條print執(zhí)行語句


    sumResult()
    print("調(diào)用完最里層函數(shù)后,再次打印外部函數(shù)的變量result的值為:"+ str(result))     #<== 第四條print執(zhí)行語句


FinalResult()
print("調(diào)用完最里層函數(shù)后,再次打印函數(shù)外的result變量:",result)    #<== 第5條print執(zhí)行語句

[小總結(jié):]

  • 我的目的是在最里層的函數(shù)sumResult里修改變量result為12,之后再調(diào)用它的外層函數(shù)中的變量result或再次調(diào)用整個(gè)函數(shù)體外的變量result時(shí), 這個(gè)result的值都是12
  • 需要兩次global申明, 遵循'申明變量的原則是,哪里用就在哪里申明'
    • 如果只在內(nèi)層函數(shù)中g(shù)lobal申明,但外層函數(shù)中的result不申明, 再次調(diào)用,函數(shù)體外邊的這個(gè)result變?yōu)?2了,外層函數(shù)中的result的值依舊是11.

</br>

函數(shù)的拆包 & 交換變量值

  • 拆包:把容器中的每一個(gè)數(shù)據(jù)拆分到不同變量進(jìn)行保存數(shù)據(jù)
  • 容器:列表,字典载矿, 元組垄潮, 字符串
  • 拆包時(shí)要注意,需要拆的數(shù)據(jù)的個(gè)數(shù)要與變量的個(gè)數(shù)相同闷盔,一一對(duì)應(yīng)弯洗,不能多,否則程序會(huì)異常

拆包

list1 = [2,3,4]
a,b,c =list1   # 拆包的時(shí)候需要一一對(duì)應(yīng),不能多
print(a, b)

tuple1 = ("張三", "李四")
name1, name2 = tuple1
print(name1, name2)

dict1 = {"name": "小新", "age": 5}.values()
value1, value2 = dict1
print(value1, value2)

str1 = "apple"
a, b, c, d, e, = str1
print(a, b, c,d,e)

上述代碼運(yùn)行結(jié)果:

2 3
張三 李四
小新 5
a p p l e

[注意:]變量名的數(shù)量一定要和容器內(nèi)元素的數(shù)量一模一樣,否則會(huì)報(bào)錯(cuò).
例: alueError: not enough values to unpack (expected 6, got 5),ValueError: too many values to unpack (expected 4)

交換兩個(gè)變量的值

  • 一般用法:
    • 通用的交換變量的方式:定義臨時(shí)變量
num1 = 1
num2 = 2

num3 = num1
num1 = num2
num2 = num3
print(num1, num2)
  • Python特有的用法
num1 = 1
num2 = 2

num1, num2 = num2, num1
print(num1, num2)

多函數(shù)程序的基本使用流程

一般在實(shí)際開發(fā)過程中逢勾,一個(gè)程序往往由多個(gè)函數(shù))組成牡整,并且多個(gè)函數(shù)共享某些數(shù)據(jù),這種場(chǎng)景是經(jīng)常出現(xiàn)的溺拱,因此下面來總結(jié)下果正,多個(gè)函數(shù)中共享數(shù)據(jù)的幾種方式:

  1. 使用全局變量
  2. 使用函數(shù)的返回值、參數(shù)
  3. 函數(shù)嵌套調(diào)用
  1. 使用全局變量
  • 多個(gè)函數(shù)可以使用同一個(gè)全局變量
  • 全局變量可以在函數(shù)里共享數(shù)據(jù)
score = 100
# 修改全局變量數(shù)據(jù)的函數(shù)
def modify():
    # 聲明修改全局變量
    global score
    # 修改全局變量
    score = 90
    print("modify:", score)

# 獲取全局變量修改后的數(shù)據(jù)
def show():
    # 獲取全局變量的數(shù)據(jù)
    print("獲取全局變量修最新的數(shù)據(jù):", score)

modify()
show()

上述代碼運(yùn)行后的結(jié)果:

modify: 90
獲取全局變量修最新的數(shù)據(jù): 90
  1. 使用函數(shù)的返回值盟迟、參數(shù)
  • 函數(shù)的返回值可以作為其他函數(shù)的參數(shù)
def return_value():
    return "哈哈"
    
def show_info(msg):
    print(msg)
    
# 1.獲取函數(shù)的返回值
value = return_value()
# 2.把函數(shù)的返回值作為其他函數(shù)的參數(shù)使用
show_info(value)

上述代碼的運(yùn)行結(jié)果:

哈哈
  1. 函數(shù)嵌套調(diào)用
def test1():
    # 通過return將一個(gè)數(shù)據(jù)結(jié)果返回
    return 20

def test2():
    # 1. 先調(diào)用test1并且把結(jié)果返回來
    result = test1()
    # 2. 對(duì)result進(jìn)行處理
    print(result)

# 調(diào)用test2時(shí)秋泳,完成所有的處理
test2()

上述代碼運(yùn)行結(jié)果:

20

總結(jié):函數(shù)使用注意事項(xiàng)

1. 自定義函數(shù)
  • 函數(shù)名不能重復(fù)

    • 如果在同一個(gè)程序中出現(xiàn)了多個(gè)相同函數(shù)名的函數(shù),那么在調(diào)用函數(shù)時(shí)就會(huì)出現(xiàn)問題攒菠,所以要避免名字相同
    • 還有一點(diǎn) 不僅要避免函數(shù)名之間不能相同迫皱,還要避免 變量名和函數(shù)名相同的,否則都會(huì)出現(xiàn)問題
  • 一個(gè)函數(shù)到底有沒有返回值辖众,就看有沒有return卓起,因?yàn)橹挥衦eturn才可以返回?cái)?shù)據(jù)

  • 在開發(fā)中往往根據(jù)需求來設(shè)計(jì)函數(shù)需不需要返回值

  • 函數(shù)中,可以有多個(gè)return語句凹炸,但是只要執(zhí)行到一個(gè)return語句戏阅,那么就意味著這個(gè)函數(shù)的調(diào)用完成

  • 在調(diào)用函數(shù)時(shí),如果需要把一些數(shù)據(jù)一起傳遞過去啤它,被調(diào)用函數(shù)就需要用參數(shù)來接收

  • 參數(shù)列表中變量的個(gè)數(shù)根據(jù)實(shí)際傳遞的數(shù)據(jù)的多少來確定

無參數(shù)奕筐、無返回值
def 函數(shù)名():
    語句
無參數(shù)、有返回值
def 函數(shù)名():
    語句
    return 需要返回的數(shù)值
有參數(shù)变骡、無返回值
def 函數(shù)名(形參列表):
    語句
有參數(shù)离赫、有返回值
def 函數(shù)名(形參列表):
    語句
    return 需要返回的數(shù)值
2.調(diào)用函數(shù)

調(diào)用的方式為:函數(shù)名([實(shí)參列表])

  • 如果調(diào)用的函數(shù) 在定義時(shí)有形參,那么在調(diào)用的時(shí)候就應(yīng)該傳遞參數(shù)
  • 調(diào)用時(shí)塌碌,實(shí)參的個(gè)數(shù)和先后順序應(yīng)該和定義函數(shù)中要求的一致
  • 如果調(diào)用的函數(shù)有返回值渊胸,那么就可以用一個(gè)變量來進(jìn)行保存這個(gè)值
3.作用域
  • 在一個(gè)函數(shù)中定義的變量,只能在本函數(shù)中用(局部變量)
  • 在函數(shù)外定義的變量台妆,可以在所有的函數(shù)中使用(全局變量)

參考資料:

擴(kuò)展閱讀:
cnblog-Python進(jìn)階-函數(shù)默認(rèn)參數(shù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末切厘,一起剝皮案震驚了整個(gè)濱河市萨咳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迂卢,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桐汤,死亡現(xiàn)場(chǎng)離奇詭異而克,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)怔毛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門员萍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拣度,你說我怎么就攤上這事碎绎。” “怎么了抗果?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵筋帖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我冤馏,道長(zhǎng)日麸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任逮光,我火速辦了婚禮代箭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涕刚。我一直安慰自己嗡综,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布杜漠。 她就那樣靜靜地躺著极景,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驾茴。 梳的紋絲不亂的頭發(fā)上戴陡,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音沟涨,去河邊找鬼恤批。 笑死,一個(gè)胖子當(dāng)著我的面吹牛裹赴,可吹牛的內(nèi)容都是我干的喜庞。 我是一名探鬼主播诀浪,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼延都!你這毒婦竟也來了雷猪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤晰房,失蹤者是張志新(化名)和其女友劉穎求摇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體殊者,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡与境,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了猖吴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摔刁。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖海蔽,靈堂內(nèi)的尸體忽然破棺而出共屈,到底是詐尸還是另有隱情,我是刑警寧澤党窜,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布拗引,位于F島的核電站,受9級(jí)特大地震影響幌衣,放射性物質(zhì)發(fā)生泄漏寺擂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一泼掠、第九天 我趴在偏房一處隱蔽的房頂上張望怔软。 院中可真熱鬧,春花似錦择镇、人聲如沸挡逼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽家坎。三九已至,卻和暖如春吝梅,著一層夾襖步出監(jiān)牢的瞬間虱疏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國打工苏携, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留做瞪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像装蓬,于是被迫代替她去往敵國和親著拭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容