函數(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ò)