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装饰器的代码 ...
随机推荐
- ASP.NET那点不为人知的事(一)
http://www.cnblogs.com/OceanEyes/archive/2012/08/13/aspnetEssential-1.html#_label0 我们上网时,在浏览器地址输入网址: ...
- 《C#高效编程》读书笔记13-正确的初始化静态成员变量
在创建某个类型实例之前,就应该初始化该实例的所有静态成员变量.而C#为此提供了静态初始化器和静态构造函数. 静态构造函数是特殊的构造函数,将在其他所有方法执行之前以及变量或属性被第一次访问之前执行. ...
- Slickflow.NET 开源工作流引擎基础介绍-.NET Core2.0 版本实现介绍 (转)
前言:.NET Core 是.NET Framework的新一代版本,是微软开发的第一个跨平台 (Windows.Mac OSX.Linux) 的应用程序开发框架(Application Framew ...
- vue-devtools插件安装
1.git clone https://github.com/vuejs/vue-devtools.git 2.此时表示vue-devtools包下载完成,进入到对应的目录下cd vue-devtoo ...
- selenium中Alter等弹出对话框的处理
昨天使用selenium做自动化测试,发现部分页面会弹出alert对话框,找了写资料,大概的意思就是要给弹出的对话框做出相应,不然,后续的处理会失败. _driver.SwitchTo().Alert ...
- System Center Configuration Manager 2016 必要条件准备篇(Part3)
步骤3.安装SQL Server 2017 注意:在Configuration Manager服务器(CM16)上以本地管理员身份执行以下操作 按照https://go.microsoft.com ...
- 解决在php5中simple XML解析错误的问题
2004年7月,php5正式版本的发布,标志着一个全新的PHP时代的到来.PHP5的最大特点是引入了面向对象的全部机制,并且保留了向下的兼容性.程序员不必再编写缺乏功能性的类,并且能够以多种方法实现类 ...
- 洛谷 P1509 找啊找啊找GF
题目背景 "找啊找啊找GF,找到一个好GF,吃顿饭啊拉拉手,你是我的好GF.再见." "诶,别再见啊..." 七夕...七夕...七夕这个日子,对于sqybi这 ...
- 将Apache2.4手动安装成Windows的服务
将Apache2.4手动安装成Windows的服务 可以选择在安装Apache时自动将其安装为一个服务.如果选择"for all users",那么Apache将会被安装为服务. ...
- segment and section for c++ elf
http://blog.csdn.net/jiafu1115/article/details/12992497 写一个汇编程序保存成文本文件max.s. 汇编器读取这个文本文件转换成目标文件max.o ...