1.1 装饰器

1、装饰器的作用

  1. 装饰器作用:本质是函数(装饰其他函数)就是为其他函数添加其他功能

  2. 装饰器必须准寻得原则

    1)不能修改被装饰函数的源代码
    2)不能修改被装饰函数的调用方式

  3.实现装饰器知识储备

    1)函数即“变量”
    2)高阶函数
    3)嵌套函数 高阶函数+潜逃函数=》装饰器

2、使用高阶函数模仿装饰器功能

    1)定义:把一个函数名当做实参传给另一个函数
    2)返回值中包含函数名
    3)下面使用高阶函数虽然可以实现装饰器的一些功能,但是违反了装饰器不能改变调用方式的原则,
         以前使用bar()现在将调用方式改编成了test1(bar)就是将bar的函数名当做变量传给了test1()

import time

def timer(func):
start_time = time.time()
func()
print '函数执行时间为', time.time() - start_time def test():
print '开始执行test'
time.sleep(3)
print 'test执行结束' timer(test)
'''
开始执行test
test执行结束
函数执行时间为 3.00332999229
'''

  4)高阶函数——不修改高阶函数的调用方式增加新的功能(但是无法传参数)
  注:bar = test2(bar) 等价于:@timer重新将函数名bar赋值,将原函数bar的内存地址当做实参传递该函数test2(),再将test2()赋值给bar

import time
def bar():
time.sleep(3)
print("in the bar")
def test2(func):
print(func)
return func
bar = test2(bar)
bar()

  5)嵌套函数
  嵌套函数:在一个函数中嵌套另一个函数,并在函数内部调用

def foo():
print("in the foo")
def bar():
print("in the bar")
bar()
foo()

  

3、装饰器1----能够适应90%的业务需求

  在装饰器中 @timer等价于 test1=timer(test1)

  1. 在timer()函数中返回值是return deco

  2. 所以timer(test1)作用是将函数test1内存地址当做参数传递给timer()

  3. timer() 函数最后将运行后的函数deco内存地址作为返回值返回

  4. test1=timer(test1)作用就是将将deco函数内存地址赋值给test1,所以最后运行test1()就相当于运行deco()

  5. 所以最后调用时给test2()传入参数就相当于给deco传入参数

import time
def timer(func): #timer(test1) func=test1
def deco(*args,**kwargs):
start_time = time.time()
func(*args,**kwargs) #run test1
stop_time = time.time()
print("running time is %s"%(stop_time-start_time))
return deco
@timer # test1=timer(test1)
def test1():
time.sleep(3)
print("in the test1")
@timer
def test2(name):
print("in the test2",name)
test1()
test2("tom")

4、装饰器2----对特定网页进行身份验证

import time
user,passwd = 'aaa','123'
def auth(func):
def wrapper(*args,**kwargs):
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and password == passwd:
print("User has passed authentication")
res = func(*args,**kwargs) #这里执行func()相当于执行调用的函数如home()
return res #为了获得home()函数返回值,可以将执行结果赋值给res然后返回print(home())结果是"from home"而不是"None"了
else:
exit("Invalid username or password")
return wrapper
def index():
print("welcome to index page")
@auth
def home():
print("welcome to home page")
return "from home"
@auth
def bbs():
print("welcome to bbs page")
index()
print(home()) #在这里调用home()相当于调用wrapper()
bbs()

5、装饰器3----终极篇:实现对不同网页不同方式的身份认证

  @auth(auth_type="local")代码作用

  1. 在上面的代码中使用@auth相当于先将home函数的内存地址当做变量传入auth()函数,执行结果后home()相当于wrapper()
  2. 而在这里验证的时候犹豫@auth(auth_type="local")中有()括号,那么就相当于将执行auth()函数而且是将auth_type="local当做参数传入到auth()函数执行
  3. 所以outer_wrapper函数也会执行,outer_wrapper函数的执行结果返回的就是wrapper()函数的内存地址
  4. 所以最终结果同样是执行home()函数就相当于执行wrapper函数
  5. 但是有所不同的是着这个版本中我们可以在外层的auth函数中传入新的参数帮组我们根据需求判断
import time
def auth(auth_type):
print("auth func:",auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print("wrapper func args:", *args, **kwargs)
print('运行前')
func(*args, **kwargs)
print('运行后')
return wrapper
return outer_wrapper @auth(auth_type="local") # home = wrapper()
def home():
print("welcome to home page")
return "from home"
home()

6、使用闭包实现装饰器功能

  1)闭包概念

    1. 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包

    2. 一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。

    3. 但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

import time

def timer(func):                    #timer(test1)  func=test1
def deco(*args,**kwargs): # # 函数嵌套
start_time = time.time()
func(*args,**kwargs) # 跨域访问,引用了外部变量func (func实质是函数内存地址)
stop_time = time.time()
print "running time is %s"%(stop_time-start_time)
return deco # 内层函数作为外层函数返回值 def test(name):
print "in the test2",name
time.sleep(2) test = timer(test) # 等价于 ==》 @timer语法糖
test("tom")
'''
运行结果:
in the test2 tom
running time is 2.00302696228
'''

1.2 生成器

定义:

  1、生成器,即生成一个容器。
  2、在Python中,一边循环,一边计算的机制,称为生成器。
  3、生成器可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己的内置iter()方法或__iter__()的内置函数),
       所以,生成器就是一个可迭代对象。

1、生成器的作用

  1. 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的。
  2. 而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
  3. 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
  4. 这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
  5. 要创建一个generator,有很多种方法,第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

print( [i*2 for i in range(10)] )             #列表生成式: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
print( (i*2 for i in range(10)) ) #生 成 器: <generator object <genexpr> at 0x005A3690>

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

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

g = (i*2 for i in range(10))
print( g.__next__() ) # 0
print( g.__next__() ) # 2

2、生成器工作原理

  1)生成器是这样一个函数,它记住上一次返回时在函数体中的位置。

  2)对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。

  3)生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

  4)生成器是一个函数,而且函数的参数都会保留。

  5)迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的

3、yield生成器运行机制

  1)Python中,yield就是这样的一个生成器。

  2)当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把yield 的参数给你,之后生成器就不会往下继续运行。

  3)当你问他要下一个数时,他会从上次的状态开始运行,直至出现yield语句,把参数给你,之后停下。如此反复

  4)在python中,当你定义一个函数,使用了yield关键字时,这个函数就是一个生成器

  5)它的执行会和其他普通的函数有很多不同,函数返回的是一个对象,而不是你平常所用return语句那样,能得到结果值。如果想取得值,那得调用next()函数

  6)每当调用一次迭代器的next函数,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出。

def fib(max_num):
a,b = 1,1
while a < max_num:
yield b
a,b=b,a+b g = fib(10) #生成一个生成器:[1,2, 3, 5, 8, 13]
print(g.__next__()) #第一次调用返回:1
print(list(g)) #把剩下元素变成列表:[2, 3, 5, 8, 13]

4、yield实现单线程下的并发效果

  1、yield相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从yield的下一条语句开始执行。

  2、send() 和next()一样,都能让生成器继续往下走一步(下次遇到yield停),但send()能传一个值,这个值作为yield表达式整体的结果

import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield
print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("老子开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i)
c2.send(i)
producer("alex") '''运行结果:
A 准备吃包子啦!
B 准备吃包子啦!
老子开始准备做包子啦!
做了2个包子!
包子[0]来了,被[A]吃了!
包子[0]来了,被[B]吃了!
做了2个包子!
包子[1]来了,被[A]吃了!
包子[1]来了,被[B]吃了!
做了2个包子!
包子[2]来了,被[A]吃了!
包子[2]来了,被[B]吃了!
做了2个包子!
包子[3]来了,被[A]吃了!
包子[3]来了,被[B]吃了!
做了2个包子!
包子[4]来了,被[A]吃了!
包子[4]来了,被[B]吃了!
做了2个包子!
包子[5]来了,被[A]吃了!
包子[5]来了,被[B]吃了!
'''

1.3 迭代器

定义:

  迭代器是访问集合内元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问一遍后结束。

1、迭代器和可迭代对象

  1. 凡是可作用于for循环的对象都是可迭代的(Iterable)类型;

  2. 凡是可作用于next()函数的对象都是迭代器(Iterator)类型,它们表示一个惰性计算的序列;

  3. 集合数据类型如listdictstr等是可迭代的但不是迭代器,不过可以通过iter()函数获得一个Iterator对象。

  4. Python的for循环本质上就是通过不断调用next()函数实现的

  总结: 一个实现了__iter__方法的对象是可迭代的,一个实现next方法的对象是迭代器

2、迭代器的两个方法

  1. 迭代器仅是一容器对象,它实现了迭代器协议。它有两个基本方法

    ㈠ next方法

     返回容器的下一个元素

    ㈡ __iter__方法

    返回迭代器自身

  2. 迭代器是访问集合内元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素都被访问一遍后结束。

  3. __iter__方法会返回一个迭代器(iterator),所谓的迭代器就是具有next方法的对象。

  4. 在调用next方法时,迭代器会返回它的下一个值,如果next方法被调用,但迭代器中没有值可以返就会引发一个StopIteration异常

a = iter([1,2,])              #生成一个迭代器
print(a.__next__())
print(a.__next__())
print(a.__next__()) #在这一步会引发 “StopIteration” 的异常

4、判断是迭代器和可迭代对象

  注:列表,元组,字典是可迭代的但不是迭代器

from collections import Iterable
print(isinstance([],Iterable)) #True
print(isinstance({},Iterable)) #True
print(isinstance((),Iterable)) #True
print(isinstance("aaa",Iterable)) #True
print(isinstance((x for x in range(10)),Iterable)) #True

5、列表不是迭代器,只有生成器是迭代器

from collections import Iterator
t = [1,2,3,4]
print(isinstance(t,Iterator)) #False
t1 = iter(t)
print(isinstance(t1,Iterator)) #True

6、自定义迭代器

class MyRange(object):
def __init__(self, n):
self.idx = 0
self.n = n def __iter__(self):
return self def next(self):
if self.idx < self.n:
val = self.idx
self.idx += 1
return self.n[val]
else:
raise StopIteration() l = [4,5,6,7,8]
obj = MyRange(l)
print obj.next() # 4
print obj.next() # 5
print obj.next() # 6 自定义迭代器

7、迭代器与生成器

l = [1,2,3,4,5]                  # 列表是一个可迭代对象,不是一个迭代器
print dir(l) # 所以 l 中有 __iter__() 方法,没有 __next__()方法
iter_obj = l.__iter__() # __iter__()方法返回迭代器对象本身(这个迭代器对象就会有 next 方法了) print '###################################\n'
print iter_obj.next() # 1
print iter_obj.next() # 2
print iter_obj.next() # 3

  

python三器的更多相关文章

  1. python三器一闭

    前言:python三器一闭i 包含 迭代器.生成器.装饰器,闭包 迭代器 概念:迭代器是一种可以记录可迭代对象遍历的位置,迭代器从第一个元素开始访问,直到访问所有元素访问结束,迭代器只会往前,不会后退 ...

  2. Python - 三大器 迭代器,生层器,装饰器

    目录 Python - 三大器 迭代器,生层器,装饰器 一. 容器 二. 可迭代对象(iterable) 三. 迭代器 四. 生成器 五. 装饰器 1. 定义 六. 闭包 Python - 三大器 迭 ...

  3. Python 入门之 Python三大器 之 装饰器

    Python 入门之 Python三大器 之 装饰器 1.开放封闭原则: (1)代码扩展进行开放 ​ 任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改.所以我们必须允许代 ...

  4. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  5. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  6. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  7. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

    摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...

  8. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

  9. Python修饰器的函数式编程

    Python的修饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西.虽然好像,他们要干的事都 ...

随机推荐

  1. 分区格式化大于2 TiB磁盘

    如果您要分区格式化一块大于2 TiB的作数据盘用的云盘(本文统一称为 大容量数据盘,小于2 TiB的数据盘统称为 小容量数据盘),您必须采用GPT分区形式.本文档描述了如何在不同的操作系统里分区格式化 ...

  2. 使用requests、re、BeautifulSoup、线程池爬取携程酒店信息并保存到Excel中

    import requests import json import re import csv import threadpool import time, random from bs4 impo ...

  3. 在列表中动态设置元素的id

    <div class="col-6" v-for="(item,i) in showpics" :key="i"> <im ...

  4. 基于webpack的vue开发环境搭建

    1.新建并初始化项目(npm int -y),安装webpack,webpack-cli webpack-dev-server 安装eslint,eslint-plugin-vue,配置eslint语 ...

  5. Gong服务实现平滑重启分析

    平滑重启是指能让我们的程序在重启的过程不中断服务,新老进程无缝衔接,实现零停机时间(Zero-Downtime)部署: 平滑重启是建立在优雅退出的基础之上的,之前一篇文章介绍了相关实现:Golang中 ...

  6. 在debian10启动器中添加自定义应用

    首先要添加一个desktop类型的文件,搜索一下即可 若将desktop文件放在/usr/share/applicatios/中,需要执行update-desktop-database使新添加的应用生 ...

  7. ASP.NET MVC通用权限管理系统(响应布局)源码更新介绍

    一.asp.net mvc 通用权限管理系统(响应布局)源码主要以下特点: AngelRM(Asp.net MVC)是基于asp.net(C#)MVC+前端bootstrap+ztree+lodash ...

  8. uniapp-使用心得

    <view class="cu-item flex-sub" :class="index==TabCur?'text-orange cur':''" v- ...

  9. python 學習深淺拷貝、集合、、作用域、函數

    python 學習深淺拷貝.集合..作用域.函數 2020開年新冠肺炎流行大部分人員.工廠.單位無法復工生產,人員隔離每天外出都要戴口罩,在家隔離期間悶壞了感覺把半年的口糧都幹掉了,嚴重考察大家的資本 ...

  10. 刷题84. Largest Rectangle in Histogram

    一.题目说明 题目84. Largest Rectangle in Histogram,给定n个非负整数(每个柱子宽度为1)形成柱状图,求该图的最大面积.题目难度是Hard! 二.我的解答 这是一个 ...