IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python 学习笔记5-函数装饰器和闭包 -> 正文阅读

[Python知识库]python 学习笔记5-函数装饰器和闭包

1.装饰器基本知识
装饰器是一个可调用的对象
@decorate
def target():
print(‘running target()’)


def target():
print(‘running target()’)
target = decorate(target)
这两种写法一样

2.装饰器通常把函数替换成另一个函数
def deco(func):
def inner():
print(‘running inner()’)
return inner

@deco
def target():
print(‘running target()’)
运行target()会发现其实在运行inner

3.装饰器在被装饰的函数定义后立即运行 通常在导入时就运行了

registry = []
def register(func):
print(‘running register(%s)’ % func)
return func

@register
def f1():
print(‘running f1’)

def f3():
print(‘running f3’)

print(‘running main()’)
f1()
f3()

最终结果为>>>
running register(<function f1 at 0x100631bf8>)
running register(<function f1 at 0x100631c80>)
running main()
running f1()
running f3
装饰器在定义函数时就运行了

4.使用装饰器 改进策略模式
上一节中提到的选择最优策略
best_promo 有一个列表存放策略 但是可能会添加了新的策略但是没有加入列表中 从而导致难以发现的问题
改进:利用装饰器
promos = []
def promotion(promo_func):
promos.append(promo_func)
return promo_func

@promotion
def fidelity(order):
return order.total() * .05 if order.customer.fidelity >= 1000 else 0

@promotion
def bulk_item(order):
pass

@promotion
def large_order(order):
pass

5.变量作用域规则
在函数中调用一个变量 如果在局部没有定义 会自动在全局中寻找并作为全局变量使用
但如果有定义的语句 则不管在定义语句的前后 这个变量都一定是局部变量 不会去寻找匹配的全局变量
也就是说 在定义之前使用就会出错

6.闭包
闭包和匿名函数不同
闭包指延伸了作用域的函数
例如实现avg()求平均值 但是可以计算不断增加的系列之的均值

avg(10)
10

avg(11)
10.5

avg(12)
11

实现方法一 类实现
class Average():
def init(self):
self.series = []
def call(self, new_values):
self.series.append(new_values)
total = sum(self.series)
return total/len(self.series)

avg = Average()#avg是Average的实例
avg(10)
avg(11)

实现方法二 高阶函数make_average
def make_average():
series = []

def average(new_value):
	series.append(new_value)
	total = sum(series)
	return total/len(series)
return average

avg = make_average()#avg是内部函数average
avg(10)
avg(11)
本来在调用avg时 函数make_avergae早就返回了 作用域也消失了
所以在average函数中series 时自由变量
series = []和后面的def average 形成了闭包 延伸到函数作用域之外了
所以闭包是一种函数 会保留定义函数时存在的自由变量的绑定

7.第6条中的series是列表 函数中的函数修改它时没有把它作为局部变量来看
但如果series是一个整型值 在函数中的函数执行series += 1 相当于定义,也就是有一个隐性的series局部变量
这时会出错 不在作为自由变量看待 可以加入 nonlocal series 来声明这不是局部变量

8.实现装饰器 输出函数的运行时间 (装饰器的特点 接受相同的参数 代替原来的函数 返回本该返回的值 同时还做些额外操作)
import time

def clock(func):
def clocked(*args):#可以接受 任意个定位参数
t0 = time.perf_counter()
result = func(*args)
elapsed = time.perf_counter() - t0
name = func.name
arg_str = ‘, ‘.join(repr(arg) for arg in args)
print(’[%0.8fs] %s(%s) -> %r’ % (elapsed, name, arg_str, result))
return result
return clocked#取代被装饰的函数

9.以上的clock装饰器有些缺点:
不支持关键字参数
遮盖了被装饰函数的__name__和__doc__属性
改进
import time
import functools
#使用了functools里的wraps 来把相关属性赋值给clocked

def clock(func):
@functools.wraps(func)
def clocked(*args, **kwargs):
t0 = time.time()
result = func(*arg, **kwargs)
elapsed = time.time() - to
name = func.name
arg_lst = []
if args :
arg_lst.append(’.’.join(repr(arg) for arg in args))
if kwargs:
pairs = [’%s=%r’ % (k,w) for k, w in sorted(kwargs.items())]
arg_lst.append(’, '.join(pairs))
arg_str = ', ‘.join(arg_lst)
print(’[%0.8fs] %s(%s) -> %r ’ % (elapsed, name, arg_str, result))
return result
return clocked

10.标准库的装饰器
property,classmethod,staticmethod
以后会讨论的

11.加入functools.lru_cache做备忘

@clock
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-2) + fibonacci(n-1)
fibonacci(6)
改进
import functools
@functools.lru_cache()
@clock
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-2) + fibonacci(n-1)
结果在P169

  1. 单分派泛函数
    使用@ingledispatch把多个函数绑定在一起组成一个泛函数

    @singleddispatch
    def htmlize(obj):
    content = html.escape(repr(obj))
    return ‘
    {}
    ’.format(content)

@htmlize.register(str)
def _(text):
pass

@htmlize.register(numbers.Intergral)
def _(n):
pass

13.叠放装饰器
@d1
@d2
def f():
pass
等同于
def f():
pass
f = d1(d2(f))

14.参数化装饰器 使得装饰器可以接受参数

registry = set()

def register(active = True):
def decorate(func):
if active:
registry.add(func)
else:
registry.discard(func)
return func
return decorate

@register(active = False)
def f1():
pass

@register()
def f2():
pass

15.参数化之前的clock装饰器
def clock(fmt=DEFAULT_FMT):
def decorate(func):
def clocked(*args):#可以接受 任意个定位参数
t0 = time.perf_counter()
result = func(*args)
elapsed = time.perf_counter() - t0
name = func.name
arg_str = ‘, ‘.join(repr(arg) for arg in args)
print(’[%0.8fs] %s(%s) -> %r’ % (elapsed, name, arg_str, result))
return result
return clocked
return decorate

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 14:02:00  更:2021-09-27 14:02:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:33:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码