装饰器、生成器、迭代器

装饰器的前奏

装饰器:本质是函数  功能:就是装饰成其他函数  就是为其他函数添加附加功能的

高阶函数+嵌套函数=装饰器

原则:1、不能修改被装饰的函数的源代码

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

总结一句话:装饰器对被装饰的函数是完全透明的

实现装饰器的只是储备:

1、函数名即“变量”   将函数体赋值给变量   和内存回收机制一样

2、高阶函数

  2.1.把函数名作为实参传递给形参(可返回被修饰函数的地址)(不修改源代码的情况可添加新的功能)

  2.2返回值中包含函数地址(不修改函数的调用方式),在原函数里需要有返回内存地址
2.1把函数名作为实参传递给形参import time
def bar():
    time.sleep(0.3)
    print("in the bar")
def test(fun):
    star_time = time.time()
    fun()
    end_time = time.time()
    print("the fun run time is %s"%(end_time-star_time))

test(bar)


2.2返回值中包含函数内容地址,不修改函数的调用方式
import time
def bar():
    star_time = time.time()
    print("in the bar")
def test(fun):
    print(fun)
    return fun      #返回值中包含函数内容地址,不修改函数的调用方式
bar=test(bar)
print(bar)
import time
def test1():
    time.sleep(3)
    print("in the test1")
def bar(fun):
    star_time=time.time()
    fun()
    end_time=time.time()
    print("the fun run time is %s"%(end_time-star_time))
    return fun
test1 = bar(test1)
test1()
结果为:
in the test1
the fun run time is 3.0
in the test1

3、嵌套函数

在一个函数里又定义了一个函数
def foo():
    print("in the foo")
    def bar():
        print("in the bar")
    bar()
foo()

函数即变量名:

装饰器

import time
def test1():
    time.sleep(3)
    print("in the test1")
def test2():
    time.sleep(3)
    print("in the test2")
def bar(fun):
    star_time = time.time()
    fun()
    end_time = time.time()
    print("the time is %s"%(end_time-star_time))
bar(test1)
bar(test2)        #用函数名赋值给形参

import time
def bar(fun):
    star_time = time.time()
    return fun
    end_time = time.time()
    print("the time is %s"%(end_time-star_time))
def test1():
    time.sleep(3)
    print("in the test1")
def test2():
    time.sleep(3)
    print("in the test2")
test1=bar(test1)
test2=bar(test2)
test1()
test2()         #不改变函数的调用方式
高阶函数+嵌套函数=装饰器
import time
def timer(fun):
    def bar():
        star_time = time.time()
        fun()
        end_time = time.time()
        print("the time is %s"%(end_time-star_time))
    return bar

def test1():
    time.sleep(3)
    print("in the test1")
def test2():
    time.sleep(3)
    print("in the test2")
test1=timer(test1)
test2=timer(test2)
test1()
test2()         #不改变函数的调用方式 为test1、test2 增加了新功能但没有改变原函数的代码
结果为:
in the test1
the time is 3.000171422958374
in the test2
the time is 3.000171661376953


import time
def timer(fun):
    def bar():
        star_time = time.time()
        fun()
        end_time = time.time()
        print("the time is %s"%(end_time-star_time))
    return bar
@timer  #要调用装饰器  在前面加@装饰器的名字
def test1():
    time.sleep(3)
    print("in the test1")
@timer  #要调用装饰器  在前面加@装饰器的名字
def test2():
    time.sleep(3)
    print("in the test2")
# test1=timer(test1)
# test2=timer(test2)      #希望直接用 test2()的格式直接调用,解释器提供了@装饰器的名字
test1()
test2()         #不改变函数的调用方式 为test1、test2 增加了新功能但没有改变原函数的代码
结果为:
in the test1
the time is 3.000171661376953
in the test2
the time is 3.000171661376953


import time
def timer(fun):
    def bar(*args,**kwargs):
        star_time = time.time()
        fun(*args,**kwargs)
        end_time = time.time()
        print("the time is %s"%(end_time-star_time))
    return bar
@timer  #要调用装饰器  在前面加@装饰器的名字
def test1():
    time.sleep(3)
    print("in the test1")
@timer  #要调用装饰器  在前面加@装饰器的名字
def test2(name,age):
    time.sleep(3)
    print("My name is %s ,have %s year old"%(name,age))
# test1=timer(test1)
# test2=timer(test2)      #希望直接用 test2()的格式直接调用,解释器提供了@装饰器的名字
test1()
test2("Mike",18)         #不改变函数的调用方式 为test1、test2 增加了新功能但没有改变原函数的代码
结果为:
in the test1
the time is 3.000171661376953
My name is Mike ,have 18 year old
the time is 3.000171422958374

带参数的装饰器

_name = "alex"
_pwd = "123"
def login(auth_type):
    def inner(fun):def bar(*wargs,**kwargs):
            if auth_type == "local":
                name = input("name:")
                pwd = input("pwd:")
                if _name==name and _pwd==pwd:
                    print("congratulations!")
                else:
                    print("the usr or pwd is invalid!")
            elif auth_type=="1dap":
                print("the usr in 1dap")
        return bar
    return inner
@login(auth_type="local")
def index(style):
    print("in the index page")
@login(auth_type="1dap")
def home():
    print("in the home page")
def bbs():
    print("in the bbs page")
index()
home()
bbs()

生成器(只有在调用的时候才会准备好数据)

生成器是边执行边计算  只有调用到对应的数据该数据才会产生(才会生成相应的数据)  和列表生成式的不同在于列表生成式在执行前已经把数据全部放在了内存里 占据了内存

生成器:省内存,因为它只记录当前的位置  对前面、后面的位置数据也是不知道的

生成器方法:只有一个__next__()方法(3.0)

      next()——2.0

c=(i*2 for i in range(100000)) ————生成器

#列表生成式,是代码更简洁
a = []
for i in range(10):
    a.append(i*2)
print(a)
结果为:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

a = (i*2 for i in range(10))     #生成器
#print(a.next())#基本不用next()获取下一个返回值
for i in a:
    print(i)
结果为:
0
2
4
6
8
10
12
14
16
18

生成器

定义generator另一种方法:

#斐波拉契数列,可以从第一个元素开始,推算出后续任意的元素
def fib(num):
    n,a,b = 0,0,1
    while n<num:
        print(b)
        a, b = b, a + b
        n+=1
fib(10)
#和generator仅一步之遥 ,把 print(b) 改成  yield(b)  这个函数就不是普通的函数  而是generator
def fib(num):
    n,a,b = 0,0,1
    while n<num:
        #print(b)
        yield (b)
        a, b = b, a + b
        n+=1
f_gen = fib(10)
print(f_gen)
结果为:<generator object fib at 0x0000000002754F30>


#generator 执行顺序和函数有点区别,区别:每次调用next()执行语句时  遇到yield语句返回,再次执行时是从上一次返回的yield语句处继续执行
def fib(num):
    n,a,b = 0,0,1
    while n<num:
        #print(b)
        yield (b)
        a, b = b, a + b
        n+=1
f_gen = fib(10)
print(f_gen.next())
print(f_gen.next())
print("先打断函数继续运行,做点别的事情")
print(f_gen.next())
结果为:
1
1
先打断函数继续运行,做点别的事情
2

用for循环拿不到generator的返回值,若想拿到要获取到StopIteration错误,返回值包含StopIteration的value中

def fib(num):
    n,a,b = 0,0,1
    while n<num:
        #print(b)
        yield (b)
        a, b = b, a + b
        n+=1
    return "done"
g = fib(6)
while True:
    try:
        x = next(g)
        print(‘g:‘, x)
    except StopIteration as e:
        print(‘Generator return value:‘, e.value)
        break
#通过yield单线程实现并发运算效果
import time
def consumer(name):
    print("%s准备开始吃包子"%name)
    while True:
        baozi = yield
        print("包子%s被%s客户食用"%(baozi,name))
def producer(name):
    c1 = consumer("A")
    c2 = consumer("B")
    c1.next()
    c2.next()
    print("开始准备做包子啦")
    for i in range(10):
        time.sleep(2)
        print("做了1个包子")
        c1.send(i)
        c2.send(i)
producer("Mike")

迭代器

1、for循环可以作用于集合数据类型、生成器      集合数据类型:字典、元组、列表、集合、字符串——————这些虽说可迭代对象  但不是迭代器  可通过内置函数iter()变成迭代器      生成器:generator  包括生成器和带yield的generator function这些作用于for循环的对象称 可迭代对象,Iterable
#字典、元组、列表、集合、字符串是可迭代对象
from collections import Iterable
print(isinstance({},Iterable))
print(isinstance([],Iterable))
print(isinstance(set(),Iterable))
print((isinstance((),Iterable)))
print(isinstance("ABC",Iterable))
**可以被next()函数调用并返回下一个值的对象称为迭代器 Iterator
可以使用isinstance判断一个对象是否是Iterator生成器一定以个迭代器,但迭代器不一定是生成器

>>> isinstance((i for a in range(10)),Iterator
True
字典、元组、列表、集合、字符串——————这些虽说可迭代对象  但不是迭代器  可通过内置函数iter()变成迭代器
>>> a=[1,2,3]
>>> iter(a)
<list_iterator object at 0x004E5690>

时间: 2024-10-20 16:06:00

装饰器、生成器、迭代器的相关文章

《Python运维开发之路》 装饰器&amp;生成器&amp;迭代器(五)

一.装饰器 装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),装饰器的功能非常强大.装饰器一般接受一个函数对象作为参数,以对其进行增强      说白了:就相当于C++中的构造函数,与析构函数 装饰器本身是一个函数,用于装饰其他函数 装饰器是一个闭包函数是嵌套函数,通过外层函数提供嵌套函数的环境 装饰器在权限控制,增加额外功能如日志,发送邮件用的比较多 1,原函数不带参数的装饰器 假设:我定义了一个函数lyshar

Python之装饰器、迭代器和生成器

在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思来谁就是对特定的建筑物内按照一定的思路和风格进行美化的一种行为,所谓“器”就是工具,对于python来说装饰器就是能够在不修改原始的代码情况下给其添加新的功能,比如一款软件上线之后,我们需要在不修改源代码和不修改被调用的方式的情况下还能为期添加新的功能,在python种就可以用装饰器来实现,同样在写

Python学习之三大名器-装饰器、迭代器、生成器

Python学习之三大名器-装饰器.迭代器.生成器 一.装饰器     装饰,顾名思义就是在原来的基础上进行美化及完善,器这里指函数,所以说装饰器就是装饰函数,也就是在不改变原来函数的代码及调用方式的前提下对原函数进行功能上的完善.其核心原理其实是利用闭包.     格式 @关键字+装饰函数          被装饰函数()      注意:@行必须顶头写而且是在被装饰函数的正上方     按照形式可以分为:无参装饰器和有参装饰器,有参装饰器即给装饰器加上参数     以下示例是一个无参装饰器,

Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化

本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########## def orter(func):    #定义装饰器     de

Python装饰器、迭代器、生成器、re正则表达式、字符串格式

本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########## def orter(func): #定义装饰器 def inner

Python装饰器、迭代器&amp;生成器、re正则表达式、字符串格式化

Python装饰器.迭代器&生成器.re正则表达式.字符串格式化 本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########

4)装饰器、迭代器、生成器以及内置函数

 装饰器.迭代器.生成器以及内置函数 装饰器: 原函数前后增加功能,切不改变函数的原本使用方式 import timedef wrapper(f):    def inner():        start = time.time()        f()        end = time.time()        print('执行效率为%s'%(end-start))    return inner @wrapperdef func():    print('this is func')

Python概念之装饰器、迭代器、生成器

装饰器.迭代器.生成器均属于函数知识范畴 1.装饰器 理解装饰器,首先要了解闭包函数. 闭包函数:1.定义在函数内部的函数: 2.该函数的函数体代码包含对外部作用域(而不是全局作用域)名字的引用: 3.通常将闭包函数用return返回,然后可以任意调用. eg:以下代码中inner()即闭包函数 def outer(): x=1 def inner(): print(x) return innerf=outer() 装饰器:即是一种闭包函数的应用. 什么是装饰器?:装饰它人的器具,本身可以是任意

Python学习之路-装饰器&生成器&正则表达式

装饰器 通俗的讲,装饰器就是在不改变源代码基础上,给源代码增加新功能. 不改变函数的源代码.调用方式.返回值等,给函数增加新功能. 经典案例:登录装饰器, def login_decorator(func):     def inner():         if USER_TEMP["status"] == False:             print("\033[31;1m用户未登录,请先登录\033[0m")             login_atm()

python函数、装饰器、迭代器、生成器

5月21日,请假结婚,然后性格惰性来了,不怎么想看视频和笔记,性格中的弱点开始出现,开始做的不错,渐渐开始松懈,直至放弃--- 函数补充进阶 函数对象 函数的嵌套 名称空间与作用域 闭包函数 函数之装饰器 函数之迭代器 函数之生成器 内置函数 一.函数补充进阶 1.函数对象:  函数是第一类对象,即函数可以当作数据传递,它的应用形式也被称为高阶函数,函数的特性如下: a. 可以被引用 1 # def foo(): 2 # print('from foo') 3 # 4 # func = foo