关闭

python学习之路-基础篇-day04

标签: python迭代器装饰器生成器序列化和反序列化
156人阅读 评论(0) 收藏 举报
分类:

大纲:
1.装饰器
2.迭代器
3.生成器
4.json和pickle的序列化和反序列化
一.装饰器decorator
1.什么是装饰器?
装饰器的本质就是返回函数的高阶函数,用来装饰其他函数,为其他函数添加一些附加的功能
装饰器的本质就是函数,他可以在其他函数不需要做任何代码变动的条件下增加额外功能,装饰器的返回值也是一个函数对象
2.装饰器的原则
1)不能修改被装饰函数的源代码
2)不能修改被装饰函数的调用方式
3.怎样实现一个装饰器呢?
1)一切皆是对象,所以在python中函数也是对象,函数可以赋值给一个变量
2)函数还可以被定义在另一个函数里面
=>一个函数可以返回另一个函数

4.装饰器详解
第一部分

import time
#先定义一个函数实现了某个功能
def test():
    time.sleep(3)
    print("i am test")
#现在来一个新的需求,我需要给这个函数增加一个计算函数运行时间的功能,怎么办呢??
#首先想到的方法是,直接在函数的内部添加
def test():
    time.sleep(3)
    print("i am test")
start_time = time.time()
test()
end_time=time.time()
print("running time is %s",end_time-start_time)
# 但是现在我有很多个类似于test的函数test1(),test2()...都需要添加同样的功能,那么逐个添加的方法效率低,
# 也会使得程序过于陇长,实在是low

第二部分–改变了函数的调用

#那么我就想单独定义计算程序运行时间的方法吧,然后进行调用
def test():
    time.sleep(3)
    print("i am test")
def timmer(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print("running time is %s", end_time - start_time)
timmer(test)
#但是这样的改法改变了代码的逻辑结果,之前运行代码只需要test(),现在却需要timmer(test),有没有更优的办法呢?

第三部分–闭包

#在此之前我们需要讲一个新的概念---闭包
def outer():
    x=10
    def inner():#inner是局部变量,全局无法直接调用#内部函数-条件1
        print(x)#x是外部环境变量-条件2
    return inner#内部函数inner就是一个闭包-结论
#我现在只想执行inner函数,执行方法有两种
#第一种outer()()
#第二种f=outer()  f()
#闭包--如果一个内部函数,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就认为是闭包
#这里内部函数是inner,外部变量是x

第四部分–重点来啦

def timmer(func):
    def deco():
       start_time = time.time()
       func()
       end_time = time.time()
       print("running time is %s", end_time - start_time)
    return deco
def test():
    time.sleep(3)
    print("i am test")
test=timmer(test)#得到的是deco函数的内存地址
test()#执行deco函数,闭包原理

第五部分-装饰器

#装饰器!!!
#新附加的功能timmer就是装饰器,可以把真正需要执行的业务包裹在里面,利用timmer来装饰test,@符号是装饰器的语法糖
#也就是省去了test=timmer(test),直接调用test就可以了
def timmer(func):#func就是返回的deco的内存地址
    def deco():
       start_time = time.time()
       func()
       end_time = time.time()
       print("running time is %s", end_time - start_time)
    return deco
@timmer
def test():
    time.sleep(3)
    print("i am test")
test()

带参数的装饰器
上面的装饰器只能实现无参数的情况,那么怎样实现带参数情况

def timmer(func):#func就是返回的deco的内存地址
    #定义一个内嵌的包装函数deco,给传入的函数加上计时功能的包装
    def deco(*args,**kwargs):
       start_time = time.time()
       func(*args,**kwargs)
       end_time = time.time()
       print("running time is %s", end_time - start_time)
    ## 将包装后的函数返回
    return deco
@timmer
def test(name,age):
    time.sleep(3)
    print("i am test",name,age)
test("coco",7)

我们再举个带参装饰器的例子加深印象

import time
def show_time(f):  #装饰器函数
    def inner(*x,**y):
        start=time.time()
        f(*x,**y)
        end=time.time()
        print("cost %s"%(end-start))
    return inner

@show_time
def foo(*a,**b):  #功能函数
    sum=0
    for i in a:
        sum+=i
    print(sum)
    time.sleep(1)
foo(1,2,3) #6

装饰器带参数

import time
def log(flag):#为了在show_time里面运用标志位,对代码进行更灵活的操作
    def show_time(f):  #装饰器函数
        def inner(*x,**y):
            start=time.time()
            f(*x,**y)
            end=time.time()
            print("cost %s"%(end-start))
            if flag=="true":
                print("log")
        return inner
    return show_time

@log("true")#@show_time
def foo(*a,**b):  #功能函数
    sum=0
    for i in a:
        sum+=i
    print(sum)
    time.sleep(1)
foo(1,2,3) #6

二.迭代器
1.什么是迭代器Iterator
a.可以直接作用于for循环的对象统称为可迭代对象(Iterable)
有哪些是可以进行for循环的对象呢?
列表,字典,元祖,字符串。。。
b.可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)

a=[1,2,3]
b=iter(a)
print(next(b))
print(next(b))
print(next(b))
#依次取出列表里面的值

总结:凡是可做for循环的对象都是可迭代的类型
凡是可做next()函数的对象都是迭代器类型
三.生成器Generator
1.生成器的使用

#通过列表生成式,我们可以直接创建一个列表,但是受到内存的限制,列表的容量是有限的,
# 所有通过列表生成的元素都是占用内存的,而我们只用到一部分的元素,这就造成了内存的浪费
x=[i*2 for i in range(10)]
print(x)#[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
print(type(x))#<class 'list'>
#等价于
x=[]
for i in range(10):
    x.append(i*2)
#在Python中,这种一边循环一边计算的机制,称为生成器,这样大大的节省了内存,创建生成器的方法有多种
#方法1,将[]改成()
x=(i*2 for i in range(10))
print(type(x))#<class 'generator'>
#进行遍历,一个元素一个元素的生成,不占用内存。生成器只有在调用时才会产生相应的数据
#只有一个__next__()方法,一般我们不这么用,等价于next(x)

2.举例斐波那契数列(任意一个数可由前面两个数相加得到)

def fib(max):
    n,a,b=0,0,1
    while n<max:
        print(b)
        a,b=b,a+b#=>相当于元祖  不是等价于a=b,b=a+b   而是x=(b,a+b)  a=x[0]   b=[a+b]
 #t=a+b  a=b  b=t  t=a
        n=n+1
fib(10)
#我们对以上的程序稍作修改
def fib(max):
    n,a,b=0,0,1
    while n<max:
        yield b  #某个函数包含了yield,这意味着这个函数已经是一个Generator
        #当调用fib函数后,整个函数都不会执行。必须通过__next__()方法才能取出里面的值
        a,b=b,a+b#=>相当于元祖  不是等价于a=b,b=a+b   而是x=(b,a+b)  a=x[0]   b=[a+b]
        n=n+1
f=fib(10)
print(f.__next__())
print(f.__next__())#调用一次__next__()就能够取出生成器里面的值

3.这里我们补充一个yield是使用,使用了yield,函数就变成了生成器啦!!!
利用yield(生成器)做一个简单的生产者消费者模型,也就是初步认识一下协程。具体什么是生产者消费者模型,什么是协程我们后面的章节会具体进行讲解

import time
def consumer(name):
    print("%s 想去商店买包子吃了"%name)
    while True:
        baozi=yield
        print("包子%s已经买到了,被%s吃了"%(baozi,name))
def product(name):
    a=consumer("coco")
    b=consumer("noki")
    a.__next__()
    b.__next__()
    print("我们商店开始生产包子并且出售啦")
    for i in range(10):
           time.sleep(1)
           a.send(i)
           b.send(i)
product("amy")

四.json和pickle序列化和反序列化
1.概念:
序列化: 将数据结构或对象转换成二进制串等的过程
反序列化:将在序列化过程中所生成的二进制串等转换成数据结构或者对象的过程
2.作用:
使用序列化主要是因为跨平台和对象存储的需求,和数据的传输(也就是不同类型语言的数据交换)
很多语言例如c,Java等都支持序列化和反序列化,这里python有两种方式可以选择json和pickle
3.json序列化和反序列化
json数据类型和python数据类型的相互转换

import json
dic={"name":"飞鸟","age":9,"sex":"F"}
print("原数据:",dic)#{"name":"飞鸟","age":9,"sex":"F"}
print("原数据类型:",type(dic))#<class 'dict'>
#我们先查看一下json到底有哪些方法
print(json.__all__)
#['dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONEncoder']
#dumps是将dict转化成str格式,loads是将str转化成dict格式
#dump和load也是类似的功能,只是与文件操作结合起来了
#1.下面将这个字典进行序列化
print("序列化后的数据:",json.dumps(dic))#{"age": 9, "name": "\u98de\u9e1f", "sex": "F"}
print("序列化后的数据类型:",type(json.dumps(dic)))#<class 'str'>
#2.进行序列化后中文变成了unicode编码,那么怎么将序列化后的中文还是中文呢?
#需要添加ensure_ascii=False
print("处理后的序列化后的数据:",json.dumps(dic,ensure_ascii=False))#{"age": 9, "name": "飞鸟", "sex": "F"}
print("处理后的序列化后的数据:",type(json.dumps(dic,ensure_ascii=False)))#<class 'str'>
#反序列化
dumps_dic=json.dumps(dic,ensure_ascii=False)
loads_dic=json.loads(dumps_dic)
print(loads_dic)#{'age': 9, 'name': '飞鸟', 'sex': 'F'}
print(type(loads_dic))#<class 'dict'>
3.文件序列化和反序列化操作
import json
#新建一个列表
li=["小米",16,"M","worker"]
print(type(li))#<class 'list'>
#将列表序列化写入文件里面,中文都要加上ensure_ascii=False,在D盘会生产新的文件
dump_li=json.dump(li,open("D:/work.txt","w"),ensure_ascii=False)
print(type(dump_li))#<class 'NoneType'>
#反序列化
load_li=json.load(open("D:/work.txt","r"))
print(type(load_li))#<class 'list'>

4.pickle序列化和反序列化

import pickle
print(pickle.__all__)

pickle和json的(dump,dumps,load,loads)的用法是一模一样的,只是将json改成pickle就可以啦
总结:
1.json是标准的数据接口格式,所以json适用于所有的语言间的数据的传输,但是pickle只适合于python间的数据传输
2.pickle不仅可以序列化常规的数据类型还可以序列化类等
3.json只能序列化字典,列表之类的常规数据类型
五.动态的获取绝对路径

0
0
查看评论

鸟哥的Linux私房菜 基础学习篇(第三版)

第零章 计算器概论 1 计算机:辅助人脑的好工具 接收用户指令与数据,经由中央处理器的数学与逻辑单元运算处理后,以产生或存储成有用的信息。 1.1 计算器的五大单元 输入单元,CPU控制单元,CPU算数逻辑单元,主存储器,输出单元 算数逻辑单元主要负责程序运算与逻辑判断。 控制单元则主要在协调周边组...
  • niuzhihuan
  • niuzhihuan
  • 2015-08-03 20:17
  • 1016

《鸟哥的linux私房菜:基础学习篇》第3版 - 核心笔记(全)

一、什么是 Linux 呢?! • Unix 与 Linux 的历史     o Multics 系统:由 Bell(贝尔实验室)、MIT(麻省理工学院)与 GE(美国通     用电器)合作开发的一个系统;     o 1969:K. ...
  • sinat_36184075
  • sinat_36184075
  • 2017-05-19 23:50
  • 620

Spark基础知识学习分享

一、Spark基础知识梳理 1.Spark是什么? Spark是一个通用的并行计算框架,由UCBerkeley的AMP实验室开发。Spark基于map reduce 算法模式实现的分布式计算,拥有Hadoop MapReduce所具有的优点;但不同于Hadoop MapReduce的是Job...
  • lantian0802
  • lantian0802
  • 2014-03-29 18:25
  • 4154

java并发编程学习总结(基础篇)

一、基础概念总结 1.多线程程序可能存在的风险: (1)安全性问题:多线程程序在没有充足同步的情况下,在特定的线程执行时序下,多个线程同时操作一块共享资源时,可能引发错误。 (2)活跃性问题:当多个线程存在竞争共享资源时,可能会引发死锁,饥饿(线程长时间得不到执行)及活锁(定义:不断的重复...
  • lantian0802
  • lantian0802
  • 2014-02-16 14:52
  • 1807

大数据的矩阵基础学习之路

课程介绍: 这是一套数学课程,适合有志于转往大数据分析领域的非数学专业人士,填补大数据的数学基础,以更好地学习更高级的数据分析挖掘、机器学习等。 课程目录: 第1课 面向小白的线性代数:矩阵基本知识,加减乘法,转置,行列式,秩,逆矩阵 第2课 计算机派上用场:常用矩阵计算工具,Exc...
  • agandjs
  • agandjs
  • 2017-10-15 11:26
  • 102

王亟亟的Python学习之路(一)-环境搭建

轉載請注明出處王亟亟的大牛之路楼主因为正好对Python这门高级语言感兴趣,然后经过一定的学习,总结下一些经验和知识点,分享给大家,这一系列会由浅至深,因为本身就不是从业余Python相关开发纯粹兴趣,如有不对请提出,谢谢哈!言归正传,这篇讲下简单的环境搭建,百度其实也有,但是还要自己找资源,楼主在...
  • ddwhan0123
  • ddwhan0123
  • 2015-10-30 13:57
  • 1891

Python之路【第三篇】:Python基础(二)

内置函数 一 详细见python文档,猛击这里 文件操作 操作文件时,一般需要经历如下步骤: 打开文件操作文件 一、打开文件 ? 1 文件句柄 = file('文件路径', '模式') 注:python中打开文件有两种方式,即:...
  • xiangxizhishi
  • xiangxizhishi
  • 2017-12-19 11:14
  • 33

Python学习之路——强力推荐的Python学习资料

资料一:程序媛想事儿(Alexia)总结 Python是一种面向对象、直译式计算机程序设计语言。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用縮进来定义语句块。与Scheme、Ruby、Perl、Tcl等动态语言一样,Python具备垃圾回收功能,能...
  • zhongwen7710
  • zhongwen7710
  • 2014-06-19 23:03
  • 6057

电子书-鸟哥的Linux私房菜--基础学习篇(第3版).pdf

http://pan.baidu.com/s/1pJmGh5L 提取密码:6u6u
  • mythling
  • mythling
  • 2014-07-27 21:14
  • 398

我的人工智能学习之路(1)

什么是人工智能,目前普遍的认识是指用人工的方法在机器上实现的智能,它能模拟和拓展人类智能。 现在主要的学派有符号主义观点,连接主义观点,和行为主义观点。 符号主义:智能的基础是知识,核心是知识表示和知识推理,因而可以建立基于知识的人类智能和机器智能的统一的理论体系。 联接主义:基于神经网络及网...
  • liudong0218
  • liudong0218
  • 2016-03-14 22:58
  • 214
    个人资料
    • 访问:5283次
    • 积分:444
    • 等级:
    • 排名:千里之外
    • 原创:40篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类