@[toc]
代理模式
proxy pattern
- 在访问某个对象之前执行一个或多个重要的额外操作
- 访问敏感信息或关键功能需要具备足够的权限
- 将计算成本较高的对象创建过程延迟到用户首次真正使用时才进行
常见类型
- 远程代理:实际存在于不同地址空间的对象在本地的代理者
- 虚拟代理:用于惰性求值,将一个大计算量对象的创建延迟到真正需要的时候进行
- 保护/防护代理:控制对敏感对象的访问
- 智能(引用)代理:在对象被访问时执行额外的动作,如计算计数或线程安全检查等
装饰器
函数式编程
- 面向对象,但更接近于数学计算
- 一种抽象程度更高的编程范式
- 允许将函数作为参数传入另一个函数
- 允许返回另一个函数
- python支持部分的函数式编程
高阶函数
- 接受另一个函数作为参数的函数
list(map(f,[x1, x2, x3, x4]))=[f(x1),f(x2),f(x3),f(x4)]
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
list(filter(f,[x1,x2,x3,x4]))=[x for x in [x1,x2,x3,x4] if f(x)]
举例
返回函数
##惰性函数
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
f = lazy_sum(1, 3, 5, 7, 9)
print(f)
print(f())
<function lazy_sum.<locals>.sum at 0x000001D4B49CDEE0>
25
对惰性函数的理解:因为惰性函数自身嵌套了子函数,所以在调用惰性函数时,实际上是调用了子函数,子函数的结果返回但不会输出。 这样在不必要的时候我们可以避免输出。
偏函数
为简化多参数函数的调用,可通过固定某参数来返回新函数,以实现简化调用。
import functools
def growth(step=1,limit=200):
g=0
while(True):
if g+step>limit:
break
g += step
return g
print(growth())
print(growth(step=3))
growth3=functools.partial(growth,step=3)
print(growth3())
print(growth3(limit=300))
200
198
198
300
闭包
返回函数不宜引用任何循环变量,或者后续会发生变化的变量
def count():
fs = []
for i in range(1, 4):
def f():
return i
fs.append(f)
print(fs)
return fs
f1, f2, f3 = count()
print(f1())
print(f2())
print(f3())
#每次存储的是子函数本身,并没有调用,结果相同
3
3
3
def count():
def f(j):
def g():
return j
return g
fs = []
for i in range(1, 4):
fs.append(f(i))
return fs
f1,f2,f3=count()
print(f1())
print(f2())
print(f3())
#增加一层子函数,每次存储最内层函数的调用实例,f(i)立刻被执行,所以返回每次不同的结果
1
2
3
装饰器
在不修改原始代码的前提下增强或扩展既有功能
- 在核心功能的基础上增加额外的功能,如授权(Authorization)、日志(Logging)
def log(func):
def wrapper(*args,**kwargs):
print("call " + func.__name__)#额外的功能
return func(*args,**kwargs) #调用原功能
return wrapper
@log #使用装饰器
def now():
pass
now() #相当于log(now)()
call now
通过装饰器后函数名称发生了变化
保持不变化,需要
functools.wraps(func)
@wraps复制了函数名称、注释文档、参数列表等,使得能够在装饰器里访问在装饰之前的函数属性
在实现装饰器时应在wrapper函数前加入@wraps,避免因函数内部功能逻辑对函数属性的依赖而导致功能错误
装饰器类
from functools import wraps
class Log:
def __init__(self,logfile='out.log'):
self.logfile=logfile
def __call__(self,func):
@wraps(func)
def wrapper(*args,**kwargs):
info="INFO: "+func.__name__+" was called"
with open(self.logfile,'a') as file:
file.write(info+'\n')
return func(*args,**kwargs)
return wrapper
@Log('test.log')#@Log()
def myfunc():
pass
myfunc()#相当于Log('test.log')(myfunc)()
INFO: myfunc was called
装饰器的顺序
- 装饰顺序:就近原则(从下往上装饰)
- 调用顺序:就远原则(从上往下调用)
property
使实例方法的调用如同实例属性
@property #读取属性
@方法名.setter #修改属性
@方法名.deleter #删除属性
也可通过property()方法获取,设置,删除,描述文档
id = property(get_id, set_id, del_id, 'id is ……')
类方法与静态方法
- 实例方法需要通过self参数隐式的传递当前类对象的实例
- 用@classmethod修饰的方法需要通过cls参数传递当前类对象,称为类方法
- 用@ststicmethod修饰的方法定义与普通函数一样,称为静态方法
- 类方法和静态方法均可通过类对象或实例对象调用
网友评论