Python学习--day4

一、装饰器

装饰器本质上也是函数,其功能是为被装饰的函数添加附加功能。装饰器的使用原则:(1)不能修改被装饰函数的源代码;(2)不能修改被装饰函数的调用方式,总之,装饰器对被装饰函数来说是透明的。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。

1、预备知识:

(1)高阶函数:把一个函数名当作实参传递给另一个函数,返回值中包含函数名

(2)嵌套函数:在一个函数体内声明一个函数,不是只调用一个函数

(3)装饰器=高阶函数+嵌套函数

2. 简单装饰器

假如要统计一个函数的执行时间,我们可以写一个统计时间的函数,然后将被统计的函数作为参数传递

 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print(‘in the bar‘)
 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)

运行结果:

in the bar
the func run time is 3.000171661376953

但是这样的话,我们每次都要将一个函数作为参数传递给test1函数。改变了函数调用方式,之前执行业务逻辑时,执行运行bar(),但是现在不得不改成test1(bar)。此时就要用到装饰器。我们就来想想办法不修改调用的代码;如果不修改调用代码,也就意味着调用bar()需要产生调用test1(bar)的效果。我们可以想到将test1赋值给bar,但是test1似乎带有一个参数……想办法把参数统一吧!如果test1(bar)不是直接产生调用效果,而是返回一个与foo参数列表一致的函数的话……就很好办了,将test1(bar)的返回值赋值给bar,然后,调用bar()的代码完全不用修改!

 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
10 def bar():
11     time.sleep(3)
12     print(‘in the bar‘)
13 bar=timmer(bar)
14 bar()

运行结果:

in the bar
the func run time is 3.000171661376953

函数timmer就是装饰器,它把执行真正业务方法的func包裹在函数里面,看起来像bar被timmer装饰了。如果我们要定义函数时使用装饰器,避免使用赋值语句bar=timmer(bar),要用到装饰器的语法糖@

 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 @timmer
10 def bar():
11     time.sleep(3)
12     print(‘in the bar‘)
13 bar()

运行结果:

in the bar
the func run time is 3.000171661376953

这样,我们就提高了程序的可重复利用性,当其他函数需要调用装饰器时,可以直接调用。装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象一样能作为参数传递给其他函数,可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。

3.带有参数的装饰器
如果要装饰的函数带有参数时

 1 import time
 2 def timmer(func):
 3     def deco(*arg,**kwarg):
 4         start_time=time.time()
 5         func(*arg,**kwarg)
 6         stop_time=time.time()
 7         print(‘the func run time is %s‘%(stop_time-start_time))
 8     return deco
 9 @timmer
10 def test1():
11     time.sleep(1)
12     print(‘in the test1‘)
13 @timmer
14 def test2(name,age) :
15     time.sleep(2)
16     print(‘in the test2:‘,name,age)
17 test1()
18 test2(‘Alex‘,18)

运行结果:

in the test1
the func run time is 1.0000572204589844
in the test2: Alex 18
the func run time is 2.0001144409179688

二、生成器

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

1. 列表生成式:如果要生成列表[1x1, 2x2, 3x3, ..., 10x10]怎么做?除了循环还可以用一行语句代替循环生成

1 list=[x*x for x in range(1,11)]
2 print(list)

运行结果:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

这种写法就是Python的列表生成式,写列表生成式时,把要生成的元素 x * x 放到前面,后面跟 for 循环,就可以把list创建出来。

2. 生成器:要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator

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

运行结果:

<generator object <genexpr> at 0x005B37E0>

创建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))

运行结果:

1
4
9

但是generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。可以通过for循环来迭代它,并且不需要关心StopIteration的错误。

1 g=(x*x for x in range(1,11))
2 for i in g:
3     print(i)

运行结果:

 1 1
 2 4
 3 9
 4 16
 5 25
 6 36
 7 49
 8 64
 9 81
10 100

3. 用函数生成generator:generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。例如,斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

1 def fib(max):
2     n,a,b=0,0,1
3     while n<max:
4         print(b)
5         a,b=b,a+b
6         n=n+1
7     return ‘done‘
8 f=fib(6)

运行结果:

1 1
2 1
3 2
4 3
5 5
6 8

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

时间: 2024-10-12 06:42:55

Python学习--day4的相关文章

python学习day4软件目录结构规范

为什么要设计好目录结构? 参考:http://www.cnblogs.com/alex3714/articles/5765046.html "设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题.对于这种风格上的规范,一直都存在两种态度: 1.一类同学认为,这种个人风格问题"无关紧要".理由是能让程序work就好,风格问题根本不是问题: 2.另一类同学认为,规范化能更好的控制程序结构,让程序具有更高的可读性: 我是比较偏向于后者的,因为

python 学习day4

函数装饰器 内置函数 编译字符串成为python代码 # s = "print(123)"# compile(s, "<string>", "exec") 执行代码.字符串.表达式 # exec("print(1+2+3)")  #代码与字符串都可以执行,但是无返回值(无返回值)# print(eval("1+2+3"))  #可以执行表达式,将执行结果当作返回值返回(有返回值) dir(dic

python学习day4之路文件的序列化和反序列化

json和pickle序列化和反序列化 json是用来实现不同程序之间的文件交互,由于不同程序之间需要进行文件信息交互,由于用python写的代码可能要与其他语言写的代码进行数据传输,json支持所有程序之间的交互,json将取代XML,由于XML格式稍微比较复杂.现在程序之间的交互都是用json来进行文件信息的交互. 在使用json序列化和反序列化的时候,dump一次,就要load一次,不能操作. json序列化的过程,就是写入文件中,让另外一个编程语言进行调用: import json in

Python学习Day4

元组tupe 元组被称为只读列表,即数据可以被查询,但不能被修改,所以字符串的切片同样适用于元组. 列表list 列表(list)是Python以及其他语言中最常用到的数据结构之一.Python使用使用中括号 [ ] 来解析列表. 列表的增加: li = ['alex','wusir','egon','女神','taibai'] li.append('大神') #增加到列表最后 >>>['alex', 'wusir', 'egon', '女神', 'taibai', '大神'] li.a

python学习day4(列表,元组)

一. 列表(增删改查)   列表可以装大量的数据,不限制数据类型. 表示为[ ]. 每一个元素之间用' , '隔开.   列表也有索引和切片 1. list: 增加: 1. append("x") 向列表中增加一个元素x. 默认添加到列表末尾   2. instert(1,"麻花藤") 将元素添加到某一个位置   3. extend("马云","麻花藤","李嘉诚") 迭代添加. 默认添加末尾 lst =

python学习:程序控制结构·作业20141219

Python学习:程序控制结构 20141219 编程环境: windows 7 x64 python 2.7.6 题目: 1 编写程序,完成下列题目(1分) 题目内容: 如果列出10以内自然数中3或5的倍数,则包括3,5,6,9.那么这些数字的和为23.要求计算得出任意正整数n以内中3或5的倍数的自然数之和. 输入格式: 一个正整数n. 输出格式: n以内中3或5的倍数的自然数之和. 输入样例: 10 输出样例: 23 时间限制:500ms内存限制:32000kb n = int(raw_in

python学习第二天

python学习的第二天就是个灾难啊,这天被打击了,自己写的作业被否认了,不说了,写博客还是个好习惯的,要坚持下去,就不知道能坚持到什么时候.呵呵!!! 这天教的知识和第一天的知识相差不大,区别在于比第一天讲的更细了(我们是两个老师教的,风格是不一样的),这次也写那些比较细的知识点. python的简介 (1)你的程序一定要有个主文件. (2)对于python,一切事物都是对象,对象基于类创建.#似懂非懂,不过有那么点似懂. 知识点 #__divmod__ 会把两个数字相除的商和余数以元组的方式

[Python 学习] 二、在Linux平台上使用Python

这一节,主要介绍在Linux平台上如何使用Python 1. Python安装. 现在大部分的发行版本都是自带Python的,所以可以不用安装.如果要安装的话,可以使用对应的系统安装指令. Fedora系统:先以root登入,运行 yum install python Ubuntu系统:在root组的用户, 运行 sudo apt-get install python 2. 使用的Python的脚本 Linux是一个以文件为单位的系统,那么我们使用的Python是哪一个文件呢? 这个可以通过指令

python学习之最简单的用户注册及登录验证小程序

文章都是从我的个人博客上粘贴过来的哦,更多内容请点击 http://www.iwangzheng.com 正如很多同学所知道的,楼主开始学习python了,前进的道路曲曲折折,有荆棘也有陷阱,从最简单的小程序写起,每天练习,将python进行到底. 有一点比较别扭的就是python的换行之后空四个空格,ruby都是两个,并且python在方法和循环语句的第一句都要加冒号 mysql> show create table user; mysql> alter table user add sal