1.装饰器

定义:给其他函数装饰(添加附加功能)的函数

原则:1.不能修改被装饰的函数的源代码。

      2.不能修改北庄施的函数的调用方式

实现所需要求:1.函数即便量

          2.高阶函数

        3.嵌套函数

    高阶函数+嵌套函数=> 装饰器

匿名函数:

 f = lambda x:x+1
print(f(1))
>>>2
#匿名函数比起正常函数,不需要指定函数名

嵌套函数:

 x = 1
def a():
x = 2
print(x)
def b():
x = 3
print(x)
def c():
x = 4
print(x)
c()
b()
a()
>>>2
3
4
#嵌套函数调用要一层一层的调用,如果b没有调用那么只会打印"2"

举一个简单的装饰器例子:

学渣版:

 def timer(func):
def deco(*args,**kwargs): #非固定参数传入
start_time = time.time() #计算开始时间
func(*args,**kwargs) #运行test1
stop_time = time.time() #计算结束时间
print("运行时间为%s" % (start_time-stop_time)) #"deco"装饰器的作用-计算test1的运行时间
return deco
@timer #还有一种调用方式,test1=timer(test1),但是这种比较麻烦还是推荐这种,你要装饰哪一个函数就在哪一个函数头部引用
def test1(a,b):
time.sleep(3) #三秒后运行
print("in the test1:%s %s" % (a,b))
test1("","") #并没有改变函数的调用方式和源代码
>>>in the test1:123 234
运行时间为-3.0027999877929688
这样应该就明白装饰器的作用了

学霸版:

 user,passwd = 'zhaoyue','woaini'
def auth(func): #这里假装我们有两个页面需要验证,这个函数用来验证
def wrapper(*args,**kwargs):
username = input("Please your username:")
password = input("Please your password")
if user == username and passwd == password:
print("Hello world!")
func(*args,**kwargs) #开始运行传入的函数
else:
exit("gun")
return wrapper #返回结果 def LOL():
print("in the LOL")
@auth
def LPL():
print("in the LPL")
@auth
def LCK():
print("in the LCK")
LOL()
LPL()
LCK() #后面则是"LPL",“LCK”需要验证。

学霸进阶版(这就是学渣和学霸的区别,一道题学渣考虑的是能不能做出来,而学霸考虑的是用几种方法做出来!!!)

 user,passwd = 'zhaoyue','woaini'
def auth(auth_type):
print("\033[32;1m%s\033[0m"% auth_type)
def outer(func):
def wrapper(*args,**kwargs):
print("wrapper func args",*args,**kwargs)
username = input("Please your username:")
password = input("Please your password:")
if user == username and passwd == password:
print("Hello world!")
res = func(*args,**kwargs)
return res
else:
exit("gun")
return wrapper
return outer def LOL():
print("in the LOL")
@auth(auth_type="local")
def LPL():
print("in the LPL")
@auth(auth_type="ldap")
def LCK():
print("in the LCK")
LOL()
LPL()
LCK()
>>>local
ldap
in the LOL
wrapper func args
Please your username:zhaoyue
Please your password:woaini
Hello world!
in the LPL
wrapper func args
Please your username:zhaoyue
Please your password:woaini
Hello world!
in the LCK

2.生成器

现在有个需求:有列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把每个值加一并打印

你可能有两种方式:

a = [0,1,2,3,4,5,6,7,8,9]
b = []
for i in a:
b.append(i+1)
print(b)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
还有就是原值修改。。太low这里就不写了

那么我们用生成器怎么写呢?

a = [i+1 for i in range(10)]
print(a)
>>>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

其实真正的生成器应该去掉[]改成(),这样它就会在你调用的时候才会出现值。举个栗子:

b = (i*3 for i in range(1000000))
print(b)
print(b.__next__()) #生成器的调用方式只有这一种b.__next__(),而且只能有一个一个的调用
print(b.__next__()) >>><generator object <genexpr> at 0x00000000023AA5C8>#这里出现个"gencerator",就是生成器的意思
0
3
#这样一个一个调用显得麻烦,所以:
b = (i*3 for i in range(1000000))
for i in b:
if i == 3000: #取值3000次
print(i)
print(i) #最后i的值
3000
2999997

在数学上有一个斐波那契数列,除了前面两个数,任意一个数都是整数前面两个数的相加

1,1,2,3,5,8,13,21,34,55.....

这里其实我们可以用生成器的方式去显示:

 def fib(max):
n,a,b = 0,0,1
while n <max:
a,b = b,a+b
print(a,b)
n += 1
return "done"
fib(15)
>>>1 1
1 2
2 3
3 5
5 8
8 13
13 21
21 34
34 55
55 89
89 144
144 233
233 377
377 610
610 987

诶。。。其实这里我们还离真正真正的生成器就差一步

 def fib(max):
n,a,b = 0,0,1
while n <max:
a,b = b,a+b
# print(a,b)
yield a,b #将print改成yield
n += 1
return "done"
f_gen = fib(15)
print(f_gen.__next__())
print("Hello world")
print(f_gen.__next__())
print(f_gen.__next__())
print("Bye world")
for i in f_gen:
print(i)
>>>(1, 1)
Hello world
(1, 2)
(2, 3)
Bye world
(3, 5)
(5, 8)
(8, 13)
(13, 21)
(21, 34)
(34, 55)
(55, 89)
(89, 144)
(144, 233)
(233, 377)
(377, 610)
(610, 987)
#这样生成器就算完成了,取值的时候可以从生成器中出来干别的,也可以随时进去,这样不会从头开始,取值取到哪里就卡在哪里

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中:

def fib(max):
n,a,b = 0,0,1
while n <max:
a,b = b,a+b
# print(a,b)
yield a,b
n += 1
return "done"
f_gen = fib(5) while True:
for i in next(f_gen):
print(i) #这样肯定会报"StopIteration",所以我们用try来捕获这个错误
while True:
try:
x = next(f_gen)
print('f_gen:',x)
except StopIteration as e: #捕获错误
print("Gen return value:",e.value) #打印错误的返回值
break

还可以使用yield实现在单线程的情况下并发运算

 import time
def xiaofeizhe(name): #不要在意这里的英文"消费者"
print('%s准备吃包子了'%name)
while True:
baozi = yield #yield就是你要把什么传到外面就写什么
print("包子[%s]被[%s]吃了"%(baozi,name )) def shangjia(): #还有这里的"商家"英文也不要在意
x1 = xiaofeizhe('A') #给"xiofeizhe(name)"传值
x2 = xiaofeizhe('B') #给"xiofeizhe(name)"传值
x1.__next__()
x2.__next__()
print("做包子ING")
for i in range(10): #循环10次把每次循环的数传给"baozi"(言外之意就是"send"可以给"yield"传值)
time.sleep(1)
x1.send(i)
x2.send(i)
shangjia()

3.迭代器

到现在,可以直接for循环的数据类型有:

list,dict,set,str还有刚学的生成器"generatior"

这些可以直接for循环的对象被称为迭代器:Iterable

可以使用"isinstance()"判断一个对象是否是Iterable对象:

 from collections import Iterable
print(isinstance([],Iterable))
>>>True
print(isinstance('str',Iterable))
>>>True
print(isinstance({},Iterable))
>>>True
print(isinstance(1,Iterable))
>>>Flase
a=(i*2 for i in range(10))
print(isinstance(a,Iterable))
>>>True

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

可以使用isinstance()判断一个对象是否是Iterator对象:

from collections import Iterator
print(isinstance([],Iterator))
>>>False
print(isinstance('str',Iterator))
>>>False
print(isinstance({},Iterator))
>>>False
print(isinstance(1,Iterator))
>>>False
a=(i*2 for i in range(10))
print(isinstance(a,Iterator))
>>>True

也就是说,list,dict,set,str这种数据类型是Iterable,Iterator对象可以被next()函数调用并不断返回下一个数据


day6-基础 装饰器,生成器,迭代器的更多相关文章

  1. Python自动化 【第四篇】:Python基础-装饰器 生成器 迭代器 Json & pickle

    目录: 装饰器 生成器 迭代器 Json & pickle 数据序列化 软件目录结构规范 1. Python装饰器 装饰器:本质是函数,(功能是装饰其它函数)就是为其他函数添加附加功能 原则: ...

  2. python三大器(装饰器/生成器/迭代器)

    1装饰器 1.1基本结构 def 外层函数(参数): def 内层函数(*args,**kwargs); return 参数(*args,**kwargs) return 内层函数 @外层函数 def ...

  3. 跟着ALEX 学python day4集合 装饰器 生成器 迭代器 json序列化

    文档内容学习于 http://www.cnblogs.com/xiaozhiqi/  装饰器 : 定义: 装饰器 本质是函数,功能是装饰其他函数,就是为其他函数添加附加功能. 原则: 1.不能修改被装 ...

  4. Day4-Python3基础-装饰器、迭代器

    今日内容: 1.高阶函数 2.嵌套函数 3.装饰器 4.生成器 5.迭代器 1.高阶函数 定义: a:把一个函数名当作实参传给函数 a:返回值包含函数名(不修改函数的调用方式) import time ...

  5. Python之函数(自定义函数,内置函数,装饰器,迭代器,生成器)

    Python之函数(自定义函数,内置函数,装饰器,迭代器,生成器) 1.初始函数 2.函数嵌套及作用域 3.装饰器 4.迭代器和生成器 6.内置函数 7.递归函数 8.匿名函数

  6. Python之装饰器、迭代器和生成器

    在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思 ...

  7. Python装饰器、迭代器&生成器、re正则表达式、字符串格式化

    Python装饰器.迭代器&生成器.re正则表达式.字符串格式化 本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用 ...

  8. 简学Python第四章__装饰器、迭代器、列表生成式

    Python第四章__装饰器.迭代器 欢迎加入Linux_Python学习群  群号:478616847 目录: 列表生成式 生成器 迭代器 单层装饰器(无参) 多层装饰器(有参) 冒泡算法 代码开发 ...

  9. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  10. python基础—装饰器

    python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...

随机推荐

  1. POJ - 3090 gcd水题

    大概题意就是求\(1 \le i,j \le n\)的\(gcd(i,j) = 1\)的个数+2(对于0的特判) 正解应该是欧拉函数或者高逼格的莫比乌斯反演 但数据实在太水直接打表算了 /*H E A ...

  2. .net core EF Cde First

    注意事项记录: public class StudentsModel { /// <summary> /// 一定需要id /// 一般用model名称+id作为表主键 /// 或者直接用 ...

  3. 使用electron构建跨平台Node.js桌面应用经验分享

    by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=6154 本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随 ...

  4. UML-1-面向对象分析和设计

    1.关键词: OOA:Object-Oriented Analysis.面向对象分析.抽取对象或概念,如:航班系统包含 飞机(Plane).航班(Flight)等概念. OOD:Object-Orie ...

  5. 设计模式学习总结(七)适配器模式(Adapter)

    适配器模式主要是通过适配器来实现接口的统一,如要实现国内手机在国外充电,则需要在不同的国家采用不同的适配器来进行兼容! 一.示例展示: 以下例子主要通过给笔记本电脑添加类似手机打电话和发短信的功能来详 ...

  6. 转帖 css的块元素、内联元素、内联块元素、display属性、浮动、定位

    块元素 块元素,也可以称为行元素,布局中常用的标签如:div.p.ul.li.h1~h6.dl.dt.dd等等都是块元素,它在布局中的行为:1.支持全部的样式.2.如果没有设置宽度,默认的宽度为父级宽 ...

  7. how to use Sqoop to import/ export data

    Sqoop is a tool designed for efficiently transferring data between RDBMS and HDFS, we can import dat ...

  8. Yii框架 多表查询实例

    Yii框架多表查询实例:总共分为两个步骤(以下的代码我全部都写在model中):1.先在主表model中声明关联表中所需要查询的字段. public $surveyls_description; // ...

  9. 水平垂直居中方案与flexbox布局

    [前端攻略]最全面的水平垂直居中方案与flexbox布局   最近又遇到许多垂直居中的问题,这是Css布局当中十分常见的一个问题,诸如定长定宽或不定长宽的各类容器的垂直居中,其实都有很多种解决方案.而 ...

  10. mysql安装 2018最新安装mysql教程及遇到的问题解决Windows下

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8094659.html 今天因为换了个LINUX系统 把我的E盘不小心给卸载了 结果还是不能用 ...