第10章 Python进阶话题
函数与命名空间
函数的全局命名空间始终是定义该函数的模块,而不是调用该函数的命名空间。
函数及其全局命名空间决定了函数中引用全局变量的值
因此,在函数中引用的全局变量始终是定义该函数模块中的全局变量
闭包及其应用(嵌套函数)
闭包:将组成函数的语句和这些语句的执行环境打包到一起所得到的对象。当使用嵌套函数时,闭包将捕获内部函数执行所需的整个环境。
嵌套的函数可以使用被嵌套函数中的任何变量,就像普通函数可以引用全局变量一样,而不需要通过参数引入。
闭包的应用是根据嵌套函数持有定义环境变量的特性来完成功能的
闭包:
def foo():
x=3
def bar():
print('x is %d'%x)
bar()
闭包与延迟求值:闭包可以实现先将参数传递给一个函数,而并不立即运行,以达到延迟求职的目的。
所谓延迟求值,就是函数返回的是一个函数,而真正需要运行函数中的代码时,其本质还是函数调用。
例:
def delay_fun(x,y):
def calculator():
return x+y
return calculator
if __name__=='__main__':
print('返回一个求和的函数,并不求和。')
msum=delay_fun(3,4)
print()
print('调用并求和:')
print(msum())
闭包与泛型函数
例:实现所有类型的一次函数的求值
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))
上下文管理器:实现上下文管理协议方法的对象,方便资源管理的一种语法形式。
上下文协议方法:
__enter__(self) #该方法是进入上下文时调用的,它创建并返回一个可以引用的资源对象,供with语句块中的程序使用
__exit__(self,type,value,tb) #该方法是推出上下文时调用的,主要用来安全地释放资源对象。参数type、value、tb用于跟踪退出错误时发生的错误类型、值和跟踪信息。
使用上下文管理器的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='')
使用这个管理文件的上下文管理器后,在每次使用文件资源时都不用写打开关闭文件的代码,就像操作一般变量一样操作就行了。
contextmanager——将生成器转变为上下文管理器的装饰器
例:
import contextlib #内置的上下文管理器的模块
@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__ 构造函数,生成对象时调用
__del__ 析构函数,释放对象时调用
__add__ 加运算
__mul__ 乘运算
__cmp__ 比较
__repr__ 打印,转换
__setitem__ 按照索引赋值
__getitem__ 按照索引获取值
__len__ 获得长度
__call__ 函数调用
鸭子类型与多态:
鸭子类型(duck typing)是动态类型的一种风格,在这种风格中,一个对象有效的语义不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定
“当看到一只鸟走起来像鸭子、游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。
在鸭子类型的语言中,编写一个函数可以接受一个任意类型的对象,并调用它的走和叫的方法。任何拥有这样的正确的走和叫方法的对象都可被函数接受。
例:
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) #报错