Python生成器、装饰器
## 生成器
- 生成器是用来创建Python序列的一个对象
- 通常生成器是为迭代器产生数据的
- 例如range()函数就是一个生成器
- 每次迭代生成器时,它都会记录上一次调用的位置,并返回下一个值,这使程序不需要创建和存储完整的序列
## 生成器函数
- 生成器函数与普通函数类似,但它的返回值使用yield语句,而不是return
def my_range(start=0, last=10, step=1):
number = start
while number < last:
yield number
number += step my_range # 是一个普通函数
# <function my_range at 0x7efe3dbf2e18> my_range() # 返回一个生成器对象
# <generator object my_range at 0x7efe3daac360> list(my_range(1, 10))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
## 装饰器
- 装饰器的作用在于在不改变原有代码结构的前提下,对原有代码的功能进行补充扩展
- 装饰器的本质上是接受函数为参数的高阶函数,它把一个函数作为参数输入并且返回一个功能拓展后的新函数
# 装饰器函数,为函数添加两条语句
def deco(fn):
def new_func(*args): # 内部函数的参数需要与传入的fn的参数相同
print("执行函数:{0}".format(fn.__name__))
result = fn(*args)
print("函数执行结果:{0}".format(result))
return result
return new_func @deco # 使用@装饰函数名,使用装饰器之后,add实际上已经指向了doco函数返回的新函数
def add(*args):
print("我是核心代码,可不能改动我")
result = 0
for n in args:
result += n
return result add(1, 2, 3, 4)
"""
执行结果:
执行函数:add
我是核心代码,可不能改动我
函数执行结果:10
"""
- 一个函数可以有多个装饰器
- 最靠近函数的装饰器会先执行,然后一次向上执行装饰器
def count_param(fn):
def new_func(*args):
amount = len(args)
fn(*args)
print("参数个数为:{0}".format(amount))
return amount
return new_func @count_param
@deco
def add(*args):
print("我是核心代码,可不能改动我")
result = 0
for n in args:
result += n
return result add(1, 2, 3, 4)
"""
执行结果:
执行函数:add
我是核心代码,可不能改动我
函数执行结果:10
参数个数为:4
"""
- 如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数
import time def log(now_time):
def deco(fn):
def new_func(*args, **kwargs):
print(now_time)
return fn(*args, **kwargs)
return new_func
return deco @log(time.asctime(time.localtime(time.time())))
def add(*args):
print("我是核心代码,可不能改动我")
result = 0
for n in args:
result += n
return result add(1, 2, 3, 4)
"""
执行结果:
函数开始时间:Sun Jul 1 15:30:14 2018
我是核心代码,可不能改动我
"""
- 此时打印add函数的__name__属性发现:
print("核心函数名:{0}".format(add.__name__))
"""
输出:
核心函数名:new_func
"""
- 这表明虽然装饰器表面上并没有改变核心函数的内容,但实际上还是对核心函数的属性进行了修改,所以还需要将核心函数的__name__属性复制到新函数
import time def log(now_time):
def deco(fn):
def new_func(*args, **kwargs):
# 将原函数的__name__属性复制到新函数
new_func.__name__ = fn.__name__
print(now_time)
return fn(*args, **kwargs)
return new_func
return deco @log(time.asctime(time.localtime(time.time())))
def add(*args):
print("我是核心代码,可不能改动我")
result = 0
for n in args:
result += n
return result add(1, 2, 3, 4)
print("核心函数名:{0}".format(add.__name__))
"""
执行结果:
Sun Jul 1 15:43:00 2018
我是核心代码,可不能改动我
核心函数名:add
"""
- 在functools里面有一个专门的函数处理这个问题
import time
import functools def log(now_time):
def deco(fn):
@functools.wraps(fn) # 在新的函数上添加装饰器,修改新函数的__name__属性
def new_func(*args, **kwargs):
print(now_time)
return fn(*args, **kwargs)
return new_func
return deco @log(time.asctime(time.localtime(time.time())))
def add(*args):
print("我是核心代码,可不能改动我")
result = 0
for n in args:
result += n
return result add(1, 2, 3, 4)
print("核心函数名:{0}".format(add.__name__))
”“”
执行结果:
Sun Jul 1 15:48:10 2018
我是核心代码,可不能改动我
核心函数名:add
“”“
- 类装饰器
class Test(object):
def __init__(self, fn):
self.fn = fn # 重写__call__函数,使实例能够像函数一样调用
def __call__(self, *args, **kwargs):
print("这是基于类的修饰")
return self.fn(*args, **kwargs) @Test
def core_func(a, b):
return a + b print(core_func(2, 3))
"""
输出:
这是基于类的修饰
5
"""
- 类装饰器带参数
import datetime
import functools class Test(object):
def __init__(self, log):
self.log = log # 重写__call__函数,使实例能够向函数一样调用
def __call__(self, fn):
@functools.wraps(fn) # 同样在这里使用functools.wraps(),将原函数__name__属性复制到新函数
def wrapper(*args, **kwargs):
print(self.log)
print("执行函数:%s" % fn.__name__)
return fn(*args, **kwargs)
return wrapper @Test(datetime.datetime.now())
def core_func(a, b):
return a + b @Test(datetime.datetime.now())
def say_hi():
print("Hi") print(core_func(2, 3))
print(core_func.__name__) # 输出:core_func
say_hi()
print(say_hi.__name__) # 输出:say_hi
"""
输出:
2018-07-02 10:55:27.258637
执行函数:core_func
5
core_func
2018-07-02 10:55:27.258696
执行函数:say_hi
Hi
say_hi
"""
本文参考:
[美]Bill Lubanovic 《Python语言及其应用》
https://www.liaoxuefeng.com 廖雪峰的官方网站
Python生成器、装饰器的更多相关文章
- Python学习---装饰器/迭代器/生成器的学习【all】
Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210
- Python之装饰器、迭代器和生成器
在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思 ...
- Python基础-迭代器&生成器&装饰器
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
- Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发
本节大纲 迭代器&生成器 装饰器 基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...
- 迭代器/生成器/装饰器 /Json & pickle 数据序列化
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- Python札记 -- 装饰器补充
本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...
- python基础——装饰器
python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
- 两个实用的Python的装饰器
两个实用的Python的装饰器 超时函数 这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,这个功能在编写外部API调用 .网络爬虫.数据库查询的时候特别有用 timeout装饰器的代码 ...
随机推荐
- [JAVA][Liferay] Configure sharding in multiple sites
create databases first portal-ext.properties配置 hibernate.dialect=org.hibernate.dialect.PostgreSQLDia ...
- hystrix应用介绍(四)
前几章已经讲了hystrix的应用场景,以及如何使用,本章我们针对如何进行hystrix参数配置做一些分析 //异步的执行 @HystrixCommand(groupKey = "testK ...
- Hibernate课程 初探多对多映射3-1 课程总结
如何通过添加中间表实现多对多? 1 在双方实体中添加一个保存对方的集合. 2 在双方映射文件中 使用<set>和<many-to-many>元素进行关联关系配置(注意此处)
- spring boot Configuration Annotation Proessor not found in classpath
出现spring boot Configuration Annotation Proessor not found in classpath的提示是在用了@ConfigurationPropertie ...
- Docker 清理命令汇总
杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器 docker rm $(docker ps -a -q) 删除所有未打 dangling ...
- 使用Ribbon Workbench来修改停用、激活按钮的权限
在实施的过程中,有时会遇到客户为了管控使用人员的操作或防止使用人员通过停用后再激活来绕开部分逻辑,需要对激活.停用按钮赋予单独的权限.但很遗憾,在Dyanmics CRM中,并没有把停用.激活按钮单独 ...
- EF--Model First
Model First先设计Model对象,再由对象生成数据库. 1.新建控制台项目,名称ModelFirst,确定. 2.点击选中项目,右键-->添加-->新建项目--选择数据模板--& ...
- 微信小程序之性能优化
如果做前端仅仅停留在编码和实现业务功能上面,可能进步速度会有些慢,但是如果经历了对页面的性能优化之后而且有所成绩的话那就不同了,因为你对他背后的机制进行了研究,才能做好性能优化. 做微信小程序也是一样 ...
- 磁盘空间满了之后MySQL会怎样
大多数用户在对于磁盘进行分区的时候都是习惯性的不给系统盘预留很大空间,其实这并不是一个好习惯.因为系统分区并不像我们想象的那样会仅仅安装一个操作系统,系统分区多数还是会承载操作系统主要应用软件安装任务 ...
- *15. 3Sum (three pointers to two pointers), hashset
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find ...