本节内容

  1. 迭代器&生成器
  2. 装饰器
  3. Json & pickle 数据序列化

一、生成器

1、列表生成式

>>> L = [x * x for x in range(10)]

>>> L

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

2、生成器

只有在调用时才会生成相应的数据,只有一个方法:__next__()方法。next(),也就是又next方法的

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

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

  1. >>> L = [x * x for x in range()]
  2.  
  3. >>> L
  4.  
  5. [, , , , , , , , , ]
  6.  
  7. >>> g = (x * x for x in range())
  8.  
  9. >>> g
  10.  
  11. <generator object <genexpr> at 0x1022ef630>

创建Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:

  1. >>> next(g)
  2.  
  3. >>> next(g)
  4.  
  5. >>> next(g)
  6.  
  7. >>> next(g)
  8.  
  9. >>> next(g)
  10.  
  11. >>> next(g)
  12.  
  13. >>> next(g)
  14.  
  15. >>> next(g)
  16.  
  17. >>> next(g)
  18.  
  19. >>> next(g)
  20.  
  21. >>> next(g)
  22.  
  23. Traceback (most recent call last):
  24.  
  25. File "<stdin>", line 1, in <module>
  26.  
  27. StopIteration

 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

普通函数:

  1. 1 def fib(max):
  2. 2 n,a,b = 0,0,1
  3. 3 while n<max:
  4. 4 print(b)
  5. 5 #yield b
  6. 6 a,b=b,a+b
  7. 7 n = n+1
  8. 8 return 'done'
  9. 9 t = fib(11)
  10. 10 print(t)
  11. 11 输出结果:
  12. 12 1
  13. 13 1
  14. 14 2
  15. 15 3
  16. 16 5
  17. 17 8
  18. 18 13
  19. 19 21
  20. 20 34
  21. 21 55
  22. 22 89
  23. 23 done
  24.  
  25. 上面函数变成生成器,只需要把print(b)改为yield b就可以了:
  26.  
  27. def fib(max):
  28.  
  29. n,a,b = 0,0,1
  30.  
  31. while n<max:
  32.  
  33. #print(b)
  34.  
  35. yield b
  36.  
  37. a,b=b,a+b
  38.  
  39. n = n+1
  40.  
  41. return 'done'
  42.  
  43. t = fib(11)
  44.  
  45. print(t)
  46.  
  47. 输出结果:
  48.  
  49. <generator object fib at 0x00000000010F59E8>

注:赋值语句:
a, b = b, a + b

相当于:

  1. t = (b, a + b) # t是一个tuple
  2. a = t[0]
  3. b = t[1]

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

变成生成器之后并没有运行,而是在要输出的时候才运行:(每次next,输出一次)

  1. def fib(max):
  2. n,a,b = 0,0,1
  3. while n<max:
  4. #print(b)
  5. yield b #碰到yield,程序中断, 出到函数外面在遇到next的时候在回来接着往下走
  6.  
  7. a,b=b,a+b
  8. n = n+1
  9. return 'done'
  10. t = fib(11)
  11. print(t)
  12. print(t.__next__())
  13. print(t.__next__())
  14. print(t.__next__())
  15. print("---------")
  16. print(t.__next__())
  17. 输出结果:
  18. 1
  19. 1
  20. 2
  21. ---------
  22. 3

再来一例:

  1. def consumer(name):
  2. print("%s 准备吃包子啦!" %name)
  3. while True:
  4. baozi = yield #碰到yield退出程序,遇到c.__next__()时在进来继续往下走
  5. print("包子[%s]来了,被【%s】吃了!" %(baozi,name))
  6. c = consumer("lsp")
  7. c.__next__()
  8. c.__next__()
  9. c.__next__()
  10. c.__next__()
  11.  
  12. 输出结果:
  13. lsp 准备吃包子啦!
  14. 包子[None]来了,被【lsp】吃了!
  15. #yield是none值,可以通过send给yield传值,见下例
  16. 包子[None]来了,被【lsp】吃了!
  17. 包子[None]来了,被【lsp】吃了!

**最后一例**

  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('lw') #因为是生成器,所以不会输出任何东西
  9. c2 = consumer('lsp')
  10. c.__next__() #输出lw准备吃包子了
  11. c2.__next__() #输出lsp准备吃包子了
  12. print("我开始准备做包子了!") #输出我开始做包子了
  13. for i in range(3): #循环
  14. time.sleep(1) #sleep 1秒
  15. print("做了1个包子") #做了一个包子
  16. c.send(i) #将i的值传给yield
  17. c2.send(i) #将i的值传给yield
  18. producer("alex") #调用函数
  19. 输出结果:
  20. lw 准备吃包子啦!
  21. lsp 准备吃包子啦!
  22. 我开始准备做包子了!
  23. 做了1个包子
  24. 包子[0]来了,被【lw】吃了!
  25. 包子[0]来了,被【lsp】吃了!
  26. 做了1个包子
  27. 包子[1]来了,被【lw】吃了!
  28. 包子[1]来了,被【lsp】吃了!
  29. 做了1个包子
  30. 包子[2]来了,被【lw】吃了!
  31. 包子[2]来了,被【lsp】吃了!

二、迭代器

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

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

只要有next的方法,就一定是一个迭代器

for line in f:   #就是一个迭代器

接上面生成器的例子:

  1. def fib(max):
  2. n,a,b = 0,0,1
  3. while n<max:
  4. #print(b)
  5. yield b
  6. a,b=b,a+b
  7. n = n+1
  8. return 'done'
  9. t = fib(11)
  10. for i in t:
  11. print(i)
  12. 输出结果:
  13. 1
  14. 1
  15. 2
  16. 3
  17. 5
  18. 8
  19. 13
  20. 21
  21. 34
  22. 55
  23. 89

三、装饰器

装饰器:本质是函数(装饰其他函数),就是为其他函数添加附加功能

原则:

  1. 不能修改被修饰的函数的源代码
  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() #调用函数bar,因为func= bar,所以这里func()== bar(),即调用上面的函数
  8. stop_time=time.time()
  9. print("the func time is %s" %(stop_time-start_time))
  10.  
  11. #bar() #原函数调用方式
  12. test1(bar) #调用函数test1,func = bar ,这样虽然实现了修改原函数功能,但是调用方式改变了

例二:

  1. 原函数:
  2. import time
  3. def test1(): # 原函数1
  4. print("this is test1")
  5. def test2(): #原函数2
  6. print("this is test2")
  7. test1() #原函数调用方式
  8. test2() #原函数调用方式
  9. -----------------------------
  10. 加装饰器(加功能:程序运行时间)
  11.  
  12. import time
  13. def timer(func):
  14. def deco():
  15. start_time = time.time()
  16. func() #test1 = func()--->test1() //#test2 = func()--->test2()
  17. stop_time = time.time()
  18. print("the func run time is %s" %(stop_time-start_time))
  19. return deco #将deco的函数的内存地址返回,就是test1 == deco函数的内存地址!
  20. @timer #test1=timer(test1) test1 == deco函数的内存地址!
  21. def test1(): #test1 == deco函数的内存地址!test1()即执行deco函数,真正的test1()到deco函数里面遇到func()才会执行
  22. time.sleep(1)
  23. print("this is test1")
  24. @timer #test2=timer(test1)
  25. def test2():
  26. time.sleep(1)
  27. print("this is test2")
  28. test1()
  29. test2()

 终极装饰器:

  1. # __author__ = 'lw'
  2. import time
  3. user,passwd = 'lw','lw123'
  4. def auth(auth_type):
  5. print('auth_func:',auth_type)
  6. def outer_wrapper(func):
  7. def wrapper(*args,**kwargs):
  8. print("wrapper func args:",*args,**kwargs)
  9. if auth_type == "local":
  10. username = input("Username:").strip()
  11. password = input("password:").strip()
  12. if username == user and passwd == password:
  13. print("\033[32;1mUser has passwd authentication\033[0m")
  14. res = func(*args,**kwargs) #from home
  15. print("---after authentication")
  16. return res
  17. else:
  18. exit("\033[31;1mInvalid username or password\033[0m")
  19. elif auth_type == "ldap":
  20. print("welcome to ldap")
  21. return wrapper
  22. return outer_wrapper
  23. def index():
  24. print("welcome to index page")
  25. @auth(auth_type="local") #home = wrapper()
  26. def home():
  27. print("welcome to home page")
  28. return "from home"
  29. def bbs():
  30. print("welcome to bbs page")
  31. index()
  32. print(home()) #wrapper()
  33. bbs()

四、 json&&pickle

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。

json在所以语言中通用

引用模块

  1. import json

重要函数

  • 编码:把一个Python对象编码转换成Json字符串   json.dumps()
  • 解码:把Json格式字符串解码转换成Python对象   json.loads()

例子

序列化

将内存中的信息写入到文件

  1. #!/usr/bin/python
  2.  
  3. import json
  4. info = {
  5.  
  6. 'name':'alex',
  7. 'age':'22'
  8. }
  9. f = open("test.txt","w")
  10.  
  11. f.write(json.dumps(info))
  12.  
  13. f.close()
  14. [root@test1 python]#

反序列化

将文件中的信息读取出来

  1. [root@test1 python]# cat fanxuliehua.py
  2. #!/usr/bin/python
  3.  
  4. import json
  5. f = open("test.txt","r")
  6.  
  7. data = json.loads(f.read())
  8.  
  9. print(data)
  10. print(data["name"])
  11.  
  12. [root@test1 python]# python fanxuliehua.py
  13. {u'age': u'22', u'name': u'alex'}
  14. alex
  15. [root@test1 python]#

json只能序列化简单的数据类型,不能反序列化函数等复杂的数据类型,想要序列化复杂的数据,需要使用pickle,用法和json完全一样,只是序列化的时候变成二进制类型,即在打开文件的时候要用wb和rb

pickle.dump(info,f) ==f.write(pickle.dumps(info))

python学习之路-day4-装饰器&json&pickle的更多相关文章

  1. Python学习之路7☞装饰器

    一:命名空间与作用域 1.1命名空间 局部命名空间: def foo(): x=1 def func(): pass 全局命名空间: import time class ClassName:pass ...

  2. Python学习之路6 - 装饰器

    装饰器 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能.原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器的知识储备: 1.函数即“变量” 2.高阶函 ...

  3. 迭代器/生成器/装饰器 /Json & pickle 数据序列化

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...

  4. 小白的Python之路 day4 装饰器前奏

    装饰器前奏: 一.定义: 1.装饰器本质是函数,语法都是用def去定义的 (函数的目的:他需要完成特定的功能) 2.装饰器的功能:就是装饰其他函数(就是为其他函数添加附加功能) 二.原则: 1. 不能 ...

  5. 小白的Python之路 day4 装饰器高潮

    首先装饰器实现的条件: 高阶函数+嵌套函数 =>装饰器 1.首先,我们先定义一个高级函数,去装饰test1函数,得不到我们想要的操作方式 import time #定义高阶函数 def deco ...

  6. Python-Day4 Python基础进阶之生成器/迭代器/装饰器/Json & pickle 数据序列化

    一.生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面 ...

  7. Python成长之路_装饰器

    一.初入装饰器 1.首先呢我们有这么一段代码,这段代码假设是N个业务部门的函数 def f1(aaa): print('我是F1业务') if aaa == 'f1': return 'ok' def ...

  8. python学习日记(函数--装饰器)

    楔子 前提,我有一段代码(一个函数). import time def run_time(): time.sleep(0.1) print('我曾踏足山巅') 需求1:现在,我想计算这段代码的运行时间 ...

  9. 【Python学习之二】装饰器

    装饰器 首先,给出装饰器的框架: def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return ...

随机推荐

  1. css3++js钟表

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. silverlight 鼠标事件处理

    托管代码注册鼠标事件 不需要再.xaml中声明注册事件. .xaml <Ellipse Name=" Fill="Orange" Canvas.Top=" ...

  3. 保持const和non-const函数代码的一致

    在用C++进行面向对象编程的时候,有时需要在一个类里包含两个代码相似的函数,而它们之间的唯一区别是,一个为const类型,一个是non-const类型. 此时如果将相同的代码写在两个函数中,则严重违反 ...

  4. 18. Word Ladder && Word Ladder II

    Word Ladder Given two words (start and end), and a dictionary, find the length of shortest transform ...

  5. 异步SRAM控制器的Verilog建模

    前言:sram顾名思义静态随机存储器,分为asram异步型和ssram同步型.这里驱动DE2上一块ISSI公司的512KB的asram. 设计思路:因为实际应用中单字节读写效率不高,所以本设计中仿照s ...

  6. EBS应用服务器启动指南

    1.ssh应用服务器    applprod用户密码:*** 管理脚本在$ADMIN_SCRIPTS_HOME路径下 adstrtal.sh       启动所有服务,命令行为adstrtal.sh ...

  7. 常见面试问题 - Useful Links

    1. Data Structure & Algorithm - 二叉树 http://baike.baidu.com/link?url=jKNdOOipbp-gloTVmSU4PT2mVB94 ...

  8. linux 源码安装

    下载源码安装包,一般为.tar.gz格式 解压源码至文件夹,linux终端进入该文件夹,安装只需三步,第四步为扫尾工作: ./configure --prefix=/usr/self/文件夹名称    ...

  9. HTML 滚动标签<marquee>

    主要参数: behavior  移动方式 scroll        循环移动 slide         只移动一个回合 alternate   来回移动 direction 移动方向 left r ...

  10. 服务器间打通ssh无密钥

    1 打通无密钥 配置HDFS,首先就得把机器之间的无密钥配置上.我们这里为了方便,把机器之间的双向无密钥都配置上. (1)产生RSA密钥信息 ssh-keygen -t rsa 一路回车,直到产生一个 ...