博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python基础(四)
阅读量:5301 次
发布时间:2019-06-14

本文共 5041 字,大约阅读时间需要 16 分钟。

一、装饰器组成

1.1 高阶函数

高阶函数代表函数作为一个值来进行调用,也成为函数调用函数。

 

1 def test1():2      print("hello")3 def test2(d):4      print("world")5 test2(test1())
View Code

 

输出结果为:

hello

world

1.2 嵌套函数

嵌套函数就是指的函数套函数。

1 def test1():2     def func():3          print("hello")4     return func()5 test1()
View Code

输出结果为:

hello

二、装饰器

1、装饰器介绍

装饰器本质上也是函数,其功能是为被装饰的函数添加附加功能。装饰器是由高阶函数和嵌套函数组成。

装饰器的使用原则:

(1)不能修改被装饰函数的源代码;

(2)不能修改被装饰函数的调用方式

总之,装饰器对被装饰函数来说是透明的。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。

 函数

2、装饰器举例

函数即变量:

1 def test():2      print("hello")3 a=test4 a()
View Code

结果输出:

hello

统计一个函数的执行时间

 

1 import time 2 def bar(): 3     time.sleep(4) 4     print("haha ni hao") 5 def test1(func): 6      start_time=time.time() 7      func() 8      stop_time=time.time() 9      print("the func run time is %s" % (stop_time - start_time))10 test1(bar)
View Code

 

输出结果:

haha ni hao

the func run time is 4.0002288818359375

 

简单装饰器

1 import time 2 def timmer(func): 3     def deco(): 4         start_time=time.time() 5         func() 6         stop_time=time.time() 7         print("the func run time is %s" % (stop_time - start_time)) 8     return deco() 9 @timmer10 def bar():11      time.sleep(4)12      print("haha ni hao")
View Code

输出结果:

haha ni hao

the func run time is 4.0002288818359375

装饰器传参:

1 import time 2 def timer(func): 3      def deco(*args,**kwargs): 4          start_time=time.time() 5          func(*args,**kwargs) 6          stop_time=time.time() 7          print("the func run time is %s" % (stop_time - start_time)) 8      return  deco 9 @timer10 def  test1():11      time.sleep(4)12      print("haha is test1")13 @timer14 def test2(name,age):15      print("name is %s,age is %s"% (name,age))16 test1()17 test2('shuaiguo',20)
View Code

输出结果:

haha is test1

the func run time is 4.000228643417358
name is shuaiguo,age is 20
the func run time is 0.0

三、生成器&迭代器

迭代器:

迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件

特点:

1.访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容

2.不能随机访问集合中的某个值 ,只能从头到尾依次访问

3.访问到一半时不能往回退

4.便于循环比较大的数据集合,节省内存

可以直接作用于for循环的数据类型有以下几种:一类是集合数据类型,如listtupledictsetstr等;一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。可以使用isinstance()判断一个对象是否是Iterable对象:

1 from collections import Iterable2 print (isinstance([],Iterable))3 print (isinstance({}, Iterable))4 print(isinstance('abc', Iterable))5 print(isinstance((x for x in range(10)), Iterable))6 print(isinstance(100, Iterable))
View Code

输出结果:

True
True
True
True
False

生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator。把listdictstrIterable变成Iterator可以使用iter()函数.

生成器:

定义: 一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器

     列表在使用前数据就已经生成了,但是我们往往只使用其中一部分数据,大部分数据用不到浪费空间。生成器generator只有在调用时才生成相应的数据。 

创建一个简单的生成器:

g=(x*x for x in range(1,11)) print(g)

生成结果:
<generator object <genexpr> at 0x00000000006A5A40>
创建listgenerator的区别仅在于最外层的[]()。list的元素我们可以一个个打印出,如果要打印generator中的元素需要借助next方法。

输出生成器里面的内容:

 

1 g=(x*x for x in range(1,11))2 print(next(g))3 print(next(g))4 print(next(g))5 for i in g:6      print(i)
View Code

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。可以通过for循环来迭代它,并且不需要关心StopIteration的错误。从下面的结果我们也可以看出for循环并没有从头开始输出而是接着第三个Next的值开始输出。

输出结果:

1

4
9
16
25
36
49
64
81
100

斐波拉契数列:

1 def fib(max):2      n, a , b = 0,0,13      while n < max:4           print(b)5           a,b=b,a+b6           n+=17      return 'done'8 fib(10)
View Code

输出结果:

1

1
2
3
5
8
13
21
34
55

注意赋值语句:

a,b =b, a+b

相当于:

t=(b,a+b) #t是一个元组

a=t[0]

b=t[1]

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

1 def fib(max): 2      n, a , b = 0,0,1 3      while n < max: 4           yield b 5           a,b=b,a+b 6           n+=1 7      return 'done' 8 f=fib(6) 9 print(f)10 print(f.__next__())11 print(f.__next__())12 print(f.__next__())
View Code

这是定义generatoe的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就是一个生成器。

结果输出:

<generator object fib at 0x0000000000AF5A40>

1
1
2

generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

1 import time 2 def consumer(name): 3      print("%s 准备吃包子啦!" % name) 4      while True: 5          baozi = yield  #碰到yield退出程序,遇到c.__next__()或者(send)时在进来继续往下走(只要有yield就是生成器) 6          print("包子【%s】来了,被【%s】吃了!" %(baozi,name)) 7 def producer(name): 8     c=consumer('zj') 9     c2 = consumer('haha')10     c.__next__() #输出zj准备吃包子了11     c2.__next__() #输出haha准备吃包子了12     print("我%s开始准备做包子了!" % name) #输出我开始做包子了13     for i in range(3):  #循环14          time.sleep(1) #sleep 1秒15          print("做了1个包子") #做了一个包子16          c.send(i) #将i的值传给yield17          c2.send(i) #将i的值传给yield18 producer('csp') #调用函数
View Code

输出结果:

zj 准备吃包子啦!
haha 准备吃包子啦!
我csp开始准备做包子了!
做了1个包子
包子【0】来了,被【zj】吃了!
包子【0】来了,被【haha】吃了!
做了1个包子
包子【1】来了,被【zj】吃了!
包子【1】来了,被【haha】吃了!
做了1个包子
包子【2】来了,被【zj】吃了!
包子【2】来了,被【haha】吃了!

 

转载于:https://www.cnblogs.com/chaishao/p/5786438.html

你可能感兴趣的文章
自建数据源(RSO2)、及数据源增强
查看>>
BootStrap2学习日记2--将固定布局换成响应式布局
查看>>
关于View控件中的Context选择
查看>>
2018icpc徐州OnlineA Hard to prepare
查看>>
Spark的启动进程详解
查看>>
使用命令创建数据库和表
查看>>
数据库的高级查询
查看>>
机器视觉:SSD Single Shot MultiBox Detector
查看>>
201521123044 《Java程序设计》第1周学习总结
查看>>
MIT Scheme 的基本使用
查看>>
程序员的“机械同感”
查看>>
在16aspx.com上下了一个简单商品房销售系统源码,怎么修改它的默认登录名和密码...
查看>>
c++回调函数
查看>>
linux下Rtree的安装
查看>>
【Java】 剑指offer(53-2) 0到n-1中缺失的数字
查看>>
Delphi中ListView类的用法
查看>>
多米诺骨牌
查看>>
Linq 学习(1) Group & Join--网摘
查看>>
asp.net 调用前台JS调用后台,后台掉前台JS
查看>>
Attribute(特性)与AOP
查看>>