python命名空間&閉包&上下文管理器&鴨子類型

函數(shù)與命名空間

函數(shù)的全局命名空間始終是定義該函數(shù)的模塊,而不是調(diào)用該函數(shù)的命名空間。

函數(shù)及其全局命名空間決定了函數(shù)中引用全局變量的值

因此,在函數(shù)中引用的全局變量始終是定義該函數(shù)模塊中的全局變量

閉包及其應(yīng)用(嵌套函數(shù))

閉包:將組成函數(shù)的語句和這些語句的執(zhí)行環(huán)境打包到一起所得到的對(duì)象。當(dāng)使用嵌套函數(shù)時(shí),閉包將捕獲內(nèi)部函數(shù)執(zhí)行所需的整個(gè)環(huán)境。

嵌套的函數(shù)可以使用被嵌套函數(shù)中的任何變量,就像普通函數(shù)可以引用全局變量一樣,而不需要通過參數(shù)引入。

閉包的應(yīng)用是根據(jù)嵌套函數(shù)持有定義環(huán)境變量的特性來完成功能的

閉包:

def foo():

??? x=3

??? def bar():

??????? print('x is %d'%x)

??? bar()

閉包與延遲求值:閉包可以實(shí)現(xiàn)先將參數(shù)傳遞給一個(gè)函數(shù),而并不立即運(yùn)行,以達(dá)到延遲求值的目的。

所謂延遲求值,就是函數(shù)返回的是一個(gè)函數(shù),而真正需要運(yùn)行函數(shù)中的代碼時(shí),其本質(zhì)還是函數(shù)調(diào)用。

例:

def delay_fun(x,y):

??? def calculator():

??????? return x+y

??? return calculator

if __name__=='__main__':

??? print('返回一個(gè)求和的函數(shù),并不求和。')

??? msum=delay_fun(3,4)

??? print()

??? print('調(diào)用并求和:')

??? print(msum())

閉包與泛型函數(shù)

例:實(shí)現(xiàn)所有類型的一次函數(shù)的求值

def line(a,b):

??? def aline(x):

??????? return a*x+b

??? return aline

if __name__=='__main__':

??? line23=line(2,3)

??? line50=line(5,0)

??? print(line23(4))

??? print(line50(2))

上下文管理器:實(shí)現(xiàn)上下文管理協(xié)議方法的對(duì)象,方便資源管理的一種語法形式。

上下文協(xié)議方法:

__enter__(self)????????? #該方法是進(jìn)入上下文時(shí)調(diào)用的,它創(chuàng)建并返回一個(gè)可以引用的資源對(duì)象,供with語句塊中的程序使用

__exit__(self,type,value,tb)?? #該方法是推出上下文時(shí)調(diào)用的,主要用來安全地釋放資源對(duì)象。參數(shù)type、value、tb用于跟蹤退出錯(cuò)誤時(shí)發(fā)生的錯(cuò)誤類型、值和跟蹤信息。

使用上下文管理器的with語句的形式為:

??? with context as var:

??????? pass

變量var將取得上下文管理器的__enter__()方法所返回的資源引用,供with后的代碼塊中使用

例:

class FileMgr:

??? def __init__(self,filename):

??????? self.filename=filename

??????? self.f=None

??? def __enter__(self):

??????? self.f=open(self.filename,encoding='utf-8')

??????? return self.f

??? def __exit__(self,t,v,tb):

??????? if self.f:

??????????? self.f.close()

if __name__=='__main__':

??? with FileMgr('10-4.py') as f:

??????? for line in f.readlines():

??????????? print(lines,end='')

使用這個(gè)管理文件的上下文管理器后,在每次使用文件資源時(shí)都不用寫打開關(guān)閉文件的代碼,就像操作一般變量一樣操作就行了。

contextmanager——將生成器轉(zhuǎn)變?yōu)樯舷挛墓芾砥鞯难b飾器

例:?

import contextlib?? #內(nèi)置的上下文管理器的模塊

@contextlib.contextmanager

def my_mgr(s,e):

?? print(s)

?? yield s+' '+e

?? print(e)

if __name__=='__main__':

?? with my_mgr('start','end') as val:

?????? print(val)

重寫類的特殊方法:

__init__? 構(gòu)造函數(shù),生成對(duì)象時(shí)調(diào)用

__del__ 析構(gòu)函數(shù),釋放對(duì)象時(shí)調(diào)用

__add__ 加運(yùn)算

__mul__ 乘運(yùn)算

__cmp__ 比較

__repr__? 打印,轉(zhuǎn)換

__setitem__? 按照索引賦值

__getitem__?? 按照索引獲取值

__len__?????? 獲得長度

__call__????? 函數(shù)調(diào)用

鴨子類型與多態(tài):

鴨子類型(duck typing)是動(dòng)態(tài)類型的一種風(fēng)格,在這種風(fēng)格中,一個(gè)對(duì)象有效的語義不是由繼承自特定的類或?qū)崿F(xiàn)特定的接口,而是由當(dāng)前方法和屬性的集合決定

“當(dāng)看到一只鳥走起來像鴨子、游泳起來像鴨子,叫起來也像鴨子,那么這只鳥就可以被稱為鴨子?!?/p>

在鴨子類型中,關(guān)注的不是對(duì)象的類型本身,而是它是如何使用的。

在鴨子類型的語言中,編寫一個(gè)函數(shù)可以接受一個(gè)任意類型的對(duì)象,并調(diào)用它的走和叫的方法。任何擁有這樣的正確的走和叫方法的對(duì)象都可被函數(shù)接受。

例:

class Duck:

??? def __init__(self,name='duck'):

??????? self.name=name

??? def quack(self):

??????? print("gagaga....")

class Cat:

??? def __init__(self,name='cat')

??????? self.name=name

??? def quack(self):

??????? print("miaomiaomiao....")

class Tree:

??? def __init__(self,name='tree')

??????? self.name=name

def duck_demo(obj):

??? obj.quack()

if __name__=='__main__':

??? duck=Duck()

??? cat=Cat()

??? tree=Tree()

??? duck_demo(duck)

??? duck_demo(cat)

??? duck_demo(tree)? #報(bào)錯(cuò)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容