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装饰器的代码 ...
随机推荐
- MyBatis01--------概念
主程序 读取配置 主配置文件 SQL映射文件 1.什么是框架? ① 框架是一个应用程序的半成品 一个框架程序员可以配置的选择.选项越多,认为这款框架的可扩展性强. 面向 ...
- [JAVA][Liferay] Configure sharding in multiple sites
create databases first portal-ext.properties配置 hibernate.dialect=org.hibernate.dialect.PostgreSQLDia ...
- mybatis批量插入insert时报错
报错信息: 传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确.此 RPC 请求中提供了过多的参数.最多应为2100 错误分析: 由于mybatis拼接的sql语句参数过多导致 解决办法 ...
- 2602 最短路径问题Dihstra算法
题目描述 Description 平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间.其中的一些点之间有连线.若有连线,则表示可从一个点到达另一个点,即两点间有通路,通 ...
- Javascript基础--数据类型
一.基本数据类型 1.字符类型:表示字符的类型,例:'aaa',"aaaa",'123456',''(空字符) 2.数字类型:表示数字的类型,例:0,1,3.1415936等 特殊 ...
- JSP 里 的 basePath
Eclipse新建JSP页面的时候不会加上 base 这个变量,需要手动添加,经常忘记,MyEclipse 就不用管了会自动添加. 如果忘了下面代码直接copy即可: <% String pat ...
- 升级jdk注意事项
最好使用和编译的jdk相同版本的jre去执行.class程序. 今天在本地模拟部署项目到tomcat6就遇到了个坑. 我们项目使用的jdk1.7开发的,编译打war包放到webapps后,启动报错Ex ...
- http相关文章目录
四种常见的 POST 提交数据方式 https://imququ.com/post/four-ways-to-post-data-in-http.html
- 深入了解MongoDB
一.介绍: 数据库分为关系型数据库和非关系型数据库 关系型数据库是建立在关系模型上的数据库,主要的有Oracle MySQL Microsoft SQL Server NoSQL是非关系型数据存储的广 ...
- IOS 运行循环
. 运行循环========================================在iOS的应用程序中,应用程序启动之后,系统即会创建一个运行循环监听用户的交互. 以下代码其本质是在运行循环 ...