# 函數(shù)(2)

## 1.函數(shù)類型

函數(shù)也是一種類型,我們自定義的函數(shù)就是函數(shù)對(duì)象,函數(shù)名保存了函數(shù)對(duì)象的引用(地址)

```

def test():

? ? print('我是測(cè)試函數(shù)')

print(test)? #函數(shù)名是變量,指向了函數(shù)對(duì)象

pf = test? ? #pf變量也指向了函數(shù)對(duì)象,所以也可以通過pf調(diào)用test函數(shù)

pf()

```

## 2. 匿名函數(shù)

不再使用def 函數(shù)名()這種形式定義函數(shù),而是使用lambda來創(chuàng)建匿名函數(shù)

特點(diǎn):

- lambda只是一個(gè)表達(dá)式,函數(shù)體比def簡(jiǎn)單的多

- lambda的函數(shù)體不再是代碼塊

- lambda只有一行,增加運(yùn)行效率

語法:

```

lambda [arg1,arg2....argn]:表達(dá)式

add = lambda a,b:a + b

print(add(3,5))

```

## 3.傳入函數(shù)

一個(gè)函數(shù)就可以接收另一個(gè)函數(shù)作為參數(shù),這種函數(shù)就稱之為高階函數(shù),也可以稱之為傳入函數(shù)。可以實(shí)現(xiàn)通用編程,排序等復(fù)雜功能

~~~

#傳入函數(shù),高階函數(shù)

#能被2整除數(shù)的和

def sum_even(n):

? ? sum = 0

? ? for i in range(1,n+1):

? ? ? ? if i % 2 == 0:

? ? ? ? ? ? sum += i

? ? return sum

#能被7整除的數(shù)的和

def sum_seven(n):

? ? sum = 0

? ? for i in range(1,n+1):

? ? ? ? if i % 7 == 0:

? ? ? ? ? ? sum += i

? ? return sum

#能被3和5整除,但不能7整除的數(shù)的和

def sum_fifteen(n):

? ? sum = 0

? ? for i in range(1,n+1):

? ? ? ? if i % 15 == 0 and i % 7 != 0:

? ? ? ? ? ? sum += i

? ? return sum

#通用求和函數(shù)

def sum1(n,callback):

? ? '''

? ? 功能:求滿足callback規(guī)定條件的數(shù)的和

? ? :param n: 大于0的整數(shù)

? ? :param callback: 用于判斷一個(gè)數(shù)是否滿足指定條件,由調(diào)用者傳入,有一個(gè)參數(shù),形如:def callback(n)

? ? :return: 求和的結(jié)果

? ? '''

? ? sum = 0

? ? for i in range(1,n+1):

? ? ? ? if callback(i):

? ? ? ? ? ? sum += i

? ? return sum

print(sum1(100,lambda x:x%2==0))

print(sum1(100,lambda x:x%7==0))

print(sum1(100,lambda x:x%15==0 and x % 7 != 0))

~~~

## 4.閉包

我們可以在一個(gè)函數(shù)中再定義一個(gè)函數(shù),在函數(shù)內(nèi)部定義的函數(shù)稱之為***內(nèi)部函數(shù)***,內(nèi)部函數(shù)只能在函數(shù)內(nèi)使用,不會(huì)污染外部空間。定義內(nèi)部函數(shù)的函數(shù)稱之為***外部函數(shù)***,這樣的定義構(gòu)成函數(shù)的嵌套

~~~

def outter(a): #外部函數(shù)

? ? x = 10

? ? def inner(y):? #內(nèi)部函數(shù)

? ? ? ? print(x + y)

? ? inner(a)


outter(20)

~~~

- 內(nèi)部函數(shù)只能在外部函數(shù)里調(diào)用,外界無法直接調(diào)用內(nèi)部函數(shù)

在一個(gè)外部函數(shù)中定義了一個(gè)內(nèi)部函數(shù),內(nèi)部函數(shù)里引用了外部函數(shù)的變量,并且外部函數(shù)的返回值是內(nèi)函數(shù)的引用。這樣內(nèi)部函數(shù)和其執(zhí)行所需的環(huán)境變量就構(gòu)成了一個(gè)***閉包***。

一般情況下,如果一個(gè)函數(shù)結(jié)束,函數(shù)的內(nèi)部所有東西都會(huì)釋放掉,局部變量都會(huì)消失。但是閉包是一種特殊情況,如果外函數(shù)在結(jié)束的時(shí)候發(fā)現(xiàn)有自己的局部變量將來會(huì)在內(nèi)部函數(shù)中用到,就把這個(gè)局部變量綁定給了內(nèi)部函數(shù),然后自己再結(jié)束。

~~~

def outter(a): #外部函數(shù)

? ? x = a

? ? def inner(y):? #內(nèi)部函數(shù)

? ? ? ? return x + y? #引用外部變量

? ? return inner? #返回內(nèi)部函數(shù)(閉包)

pf = outter(20)

print(pf(10))? #30

print(pf(20))? #40

~~~

在閉包中無法直接修改外部變量x的值

~~~

def outter(a): #外部函數(shù)

? ? x = a

? ? def inner(y):? #內(nèi)部函數(shù)

? ? ? # x += 10? #UnboundLocalError: local variable 'x' referenced before assignment

? ? ? ? return x + y

? ? return inner

~~~

在python3中可以通過nonlocal關(guān)鍵字聲明一下x,表示這個(gè)變量不是局部變量,需要向上一層變量空間找這個(gè)變量。

~~~

def outter(a): #外部函數(shù)

? ? x = a

? ? def inner(y):? #內(nèi)部函數(shù)

? ? ? ? nonlocal x

? ? ? ? x += 10

? ? ? ? return x + y

? ? return inner

~~~

## 5.偏函數(shù)

當(dāng)一個(gè)函數(shù)有大量參數(shù),調(diào)用的時(shí)候非常不方便,可以使用偏函數(shù)技術(shù),將一些參數(shù)固定(給默認(rèn)值),達(dá)到簡(jiǎn)化函數(shù)調(diào)用的目的。

~~~

import functools

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

? ? print(a, b, c, d)

#從前面固定參數(shù),使用位置參數(shù)就行,1=>a,2=>b

test1 = functools.partial(test,1,2)

test1(3,4)? #3=>c? 4=>d

#從后面固定參數(shù),需要使用關(guān)鍵字參數(shù)

test2 = functools.partial(test,c=3,d=4)

test2(1,2)? #1=>a 2=>b

#如果固定的參數(shù)不連續(xù),則需使用關(guān)鍵字參數(shù)固定

test3 = functools.partial(test,b=2,d=4)

test3(a=1,c=3) #需要使用關(guān)鍵字參數(shù),否則會(huì)報(bào)錯(cuò)

~~~

## 6.變量的作用域

程序中的變量并不是在任意的位置都可以隨意訪問,在哪里可以訪問取決于這個(gè)變量的作用域,變量的作用域指的是變量在那段代碼中可以使用,可以使用變量的那段代碼就是變量的作用域。在python中,只有函數(shù)/類/模塊才引入作用域,if/elif/else , while/for,try/except等并不會(huì)引入新的作用域

~~~

#if語句不引入新作用域,msg在外面可以使用

if True:

? ? msg = "message"

print(msg)

~~~

### 6.1 變量作用域的分類

按照作用域劃分,可以分為:

- L:Local,局部作用域?

- E:Enclosing,閉包作用域【閉包外的函數(shù)中定義的變量】

- G:Global,全局作用域? 在所有函數(shù)外定義的變量

- B:Built-in,內(nèi)建作用域【內(nèi)置作用域】

~~~

#1 局部作用域?

#局部變量只能在函數(shù)內(nèi)部使用,外部無法引用

#局部變量的作用域從定義開始到函數(shù)體結(jié)束

def demo():

? ? num = 20? #局部變量?

? ? print(num)

demo()

#print(num) 錯(cuò)誤

#閉包作用域

#

def outter():

? x = 10? #函數(shù)作用域,從定義開始到本函數(shù)結(jié)束

? def inner():

? ? ? y = x? #在閉包中可以引用

? ? ? print(y)

? return inner

pf = outter()

pf()? #執(zhí)行閉包

print(pf.__closure__)

#全局作用域

x = 100? ? #全局作用域? 從定義開始到本文件結(jié)束

def demo():

? print(x)

print(x)

#內(nèi)建作用域,是指系統(tǒng)內(nèi)建的函數(shù)或常量,在系統(tǒng)載入時(shí)加載,在所有模塊中都可以直接引用

#比如說系統(tǒng)函數(shù)

print(max(1,2,3))? #max函數(shù)就是內(nèi)建作用域? 哪里都可以引用

def? demo():

? ? x = 30

? ? y = 50

? ? print(max(x, y))

~~~

### 6.2 變量作用域查找規(guī)則

以 L --> E --> G -->B 的規(guī)則查找,即:在局部找不到,便會(huì)去局部外的局部找(例如閉包),再找不到就會(huì)去全局找,最后到內(nèi)建作用域中找。

### 6.3 全局變量和局部變量

定義在函數(shù)內(nèi)部的變量擁有一個(gè)局部作用域,被稱為局部變量

定義在函數(shù)外面的變量擁有一個(gè)全局作用域,被稱為全局變量

~~~

total = 0? #全局變量

def sum(arg1,arg2):

? ? total = arg1 + arg2? #局部變量

? ? print("函數(shù)內(nèi)部:",total)

? ? return total


sum(10,20)

#print(total1)

print("函數(shù)外部:",total)

num = 1

def fun1():

? ? print(num) #UnboundLocalError: local variable 'num' referenced before assignment

? ? num = 123

? ? print(num)

fun1()

~~~

### 6.4 global和nonlocal

~~~

#1.在Python中,當(dāng)內(nèi)部作用域想修改外部作用域的變量的時(shí)候,則就要使用global關(guān)鍵字進(jìn)行聲明

num = 1

def fun1():

? ? global num? #告訴編譯器,此處的num是全局變量

? ? print(num)? #1

? ? num = 123

? ? print(num)? #123

fun1()

a = 10

def test():

? ? global? a

? ? a = a + 1

? ? print(a)

test()

#2.如果要修改函數(shù)作用域中的變量,則使用nonlocal

#需要明確的是,nonlocal關(guān)鍵字定義在閉包里面

x = 0? #全局作用域

def outer():

? ? x = 1? #函數(shù)作用域

? ? def inner():

? ? ? ? nonlocal x

? ? ? ? x = 2? #局部作用域

? ? ? ? print("inner:",x)? #2

? ? inner()

? ? print("outer:",x)? #1---->2

outer()

print("全局:",x)? #0

#nonlocal關(guān)鍵字:聲明了該變量不只是在inner函數(shù)內(nèi)部才有效,而是在整個(gè)outer函數(shù)中有效

~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,637評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,629評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,976評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評(píng)論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,139評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,686評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,411評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,641評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,820評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評(píng)論 1 295
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,362評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,604評(píng)論 2 380

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