欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

[转载] python迭代器、生成器和装饰器

发布时间:2025/3/11 python 39 豆豆
生活随笔 收集整理的这篇文章主要介绍了 [转载] python迭代器、生成器和装饰器 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

参考链接: 有效地在Python中使用迭代

文章目录

 生成器生成器表达式(generator expression)通过使用yield关键字定义生成器并行前戏高潮

  

  迭代器迭代器概述iter()函数 创建迭代器创建一个迭代器(类)内置迭代器工具count无限迭代器cycle 无限迭代器,从一个有限序列中生成无限序列:itertools的子模块 islice 控制无限迭代器输出的方式

  

  装饰器高阶函数嵌套函数高阶函数+嵌套函数 = 装饰器类装饰器带参数的decorator实例---登录认证

 

 

 

生成器 

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

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

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

生成器表达式(generator expression) 

L = [x + 1 for x in range(10)]

print(L)

 

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

列表生成式复习 

实现列表元素加1,列表生成式与其它方法比较: 

#普通方法1

b = []

for i in range(10):

    b.append(i+1)

print(b)

 

#普通方法2

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

for index,i in enumerate(a):

    a[index] +=1

print(a)

 

#map,lambda

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

a = map(lambda x:x+1, a)

print(list(a))

 

 

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

g = (x + 1 for x in range(10))

print(g)

 

<generator object <genexpr> at 0x7fe03ad859a8>

 

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

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

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

next(g)

 

1

 

next(g)

 

2

 

next(g)

 

3

 

g.__next__()

 

4

 

g.__next__()

 

5

 

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误 

上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象: 

g = (x * x for x in range(10))

for n in g:

    print(n,end=";")

 

0;1;4;9;16;25;36;49;64;81;

 

所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误 

通过使用yield关键字定义 

生成器对象是通过使用yield关键字定义的函数对象,因此,生成器也是一个函数。生成器用于生成一个值得序列,以便在迭代器中使用。 

"""

第一是直接作为脚本执行,

第二是import到其他的python脚本中被调用(模块重用)执行。

因此if __name__ == '__main__': 的作用就是控制这两种情况执行代码的过程,

在if __name__ == '__main__':下的代码只有在第一种情况下(即文件作为脚本直接执行)才会被执行,而import到其他脚本中是不会被执行的。

"""

 

def myYield(n):

    while n>0:

        print('开始生成。。。')

        yield n

        print('完成一次。。。')

        n -= 1

if __name__ == '__main__':

    a = myYield(3)

    print('已经实例化生成器对象')

#     a.__next__()

#     print('第二次调用__next__()方法:')

#     a.__next__()

 

已经实例化生成器对象

 

yield 语句是生成器中的关键语句,生成器在实例化时并不会被执行,而是等待调用其__next__()方法才开始运行。并且当程序运行完yield语句后就会“吼(hold)住”,即保持当前状态且停止运行,等待下一次遍历时才恢复运行。 

程序运行的结果中的空行后的输出“已经实例化生成器对象”之前,已经实例化了生成器对象,但生成器并没有运行(没有输出‘开始生成’)。当第一次手工调用__next__()方法之后,才输出‘开始生成’,标志着生成器已经运行,而在输出‘’第二次调用__next__()方法‘’之前并没有输出‘完成一次’,说明yield语句运行之后就立即停止了。而第二次调用__next__()方法之后,才输出‘完成一次’,说明生成器的回复运行是从yield语句之后开始运行的 

return_value = a.__next__()

print(return_value)

 

开始生成。。。

3

 

print('第二次调用__next__()方法:')

 

第二次调用__next__()方法:

 

return_value = a.__next__()

print(return_value)

 

完成一次。。。

开始生成。。。

2

 

著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到: 

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易: 

def fib(max):

    n, a, b = 0, 0, 1

    while n < max:

        print(b)

        a, b = b, a + b

        n = n + 1

    return 'done'

 

注意,赋值语句: 

a, b = b, a + b

 

相当于: 

t = (b, a + b) # t是一个tuple

a = t[0]

b = t[1]

 

上面的函数可以输出斐波那契数列的前N个数: 

fib(5)

 

1

1

2

3

5

 

 

 

 

 

'done'

 

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

def fib(max):

    n,a,b = 0,0,1

    while n < max:

        #print(b)

        yield  b

        a,b = b,a+b

        n += 1

    return 'well done' 

 

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

f = fib(5)

print(f)

print(list(f))

 

#重新实例化生成器对象

f = fib(5)

 

<generator object fib at 0x7fe038493840>

[1, 1, 2, 3, 5]

 

print(f.__next__())

print(f.__next__())

print("干点别的事")

print(f.__next__())

print(f.__next__())

print(f.__next__())

print(f.__next__())

 

1

1

干点别的事

2

3

5

 

 

 

---------------------------------------------------------------------------

 

StopIteration                             Traceback (most recent call last)

 

<ipython-input-18-9609f54647c6> in <module>

      5 print(f.__next__())

      6 print(f.__next__())

----> 7 print(f.__next__())

 

 

StopIteration: well done

 

用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中: 

g = fib(6)

while True:

    try:

        x = next(g)

        print('g:', x)

    except StopIteration as e:

        print('Generator return value:', e.value)

        break

 

g: 1

g: 1

g: 2

g: 3

g: 5

g: 8

Generator return value: well done

 

from itertools import islice

def fib():

    a,b = 0,1

    while True:

        yield b

        a,b = b,a+b

f = fib()

print(list(islice(f ,0,10)))

 

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

 

生成器在Python中是一个非常强大的编程结构,可以用更少地中间变量写流式代码,此外,相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。现在就可以动手重构你的代码了,但凡看到类似 

def something():

    result= []

    for ... in ...:

        result.append(x)

        return result

 

都可以用生成器函数来替换: 

def iter_something():

    result = []

    for ... in ...:

        yield x

 

杨辉三角 

期待输出: 

[1]

[1, 1]

[1, 2, 1]

[1, 3, 3, 1]

[1, 4, 6, 4, 1]

[1, 5, 10, 10, 5, 1]

[1, 6, 15, 20, 15, 6, 1]

[1, 7, 21, 35, 35, 21, 7, 1]

[1, 8, 28, 56, 70, 56, 28, 8, 1]

[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

 

def triangles():

    result = [1]

    while True:

        yield result

        result = [1] + [result[i] + result[i+1] for i in range(len(result)-1)] + [1]

 

n = 0

results = []

for t in triangles():

    print(t)

    results.append(t)

    n = n + 1

    if n == 10:

        break

if results == [

    [1],

    [1, 1],

    [1, 2, 1],

    [1, 3, 3, 1],

    [1, 4, 6, 4, 1],

    [1, 5, 10, 10, 5, 1],

    [1, 6, 15, 20, 15, 6, 1],

    [1, 7, 21, 35, 35, 21, 7, 1],

    [1, 8, 28, 56, 70, 56, 28, 8, 1],

    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

]:

    print('测试通过!')

else:

    print('测试失败!')

 

 

[1]

[1, 1]

[1, 2, 1]

[1, 3, 3, 1]

[1, 4, 6, 4, 1]

[1, 5, 10, 10, 5, 1]

[1, 6, 15, 20, 15, 6, 1]

[1, 7, 21, 35, 35, 21, 7, 1]

[1, 8, 28, 56, 70, 56, 28, 8, 1]

[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

测试通过!

 

生成器并行 

前戏 

def gen():

    a = yield 1

    print('yield a % s' % a)

    b = yield 2

    print('yield b % s' % b)

    c = yield 3

    print('yield c % s' % c)

    return "happy ending"

 

 

r = gen()

x = next(r)

print('next x %s' % x)

y = r.send(10)

print('next y %s' %y)

z = next(r)

print('next z %s' % z)

try:

    a = next(r)

except StopIteration as e:

    print(e)

 

 

next x 1

yield a 10

next y 2

yield b None

next z 3

yield c None

happy ending

 

运行过程说明: 

第一步:r = gen(),实例化一个生成器对象第二步:调用next() ,遇到yield 暂停,返回值1,赋值给x第三步:打印x的值第四步:传值10,在暂停处接受值10,赋值给a,继续运行,打印a的值,遇到第二个yield,暂停,返回值2,赋值给y第五步:打印y的值第六步:调用next() ,打印b值,遇到第三个yield暂停,返回值3,赋值给z第七步:打印z值第八步:调用next(),打印c的值,报StopIteration错误,用try。。。except捕获错误 

高潮 

import time

import random

 

food = ["韭菜鸡蛋","猪肉白菜","猪肉荠菜","羊肉白菜","猪肉大葱","虾仁海鲜"]

 

 

def consumer(name):

    print("%s 准备吃包子啦!" %name)

    while True:

        baozi = yield 'n'

        print("[%s]馅包子来了,被[%s]吃了!" %(baozi,name))

 

        

def producer(name):

    c1 = consumer('大儿子')

    c2 = consumer('小儿子')

    c1.__next__()

    c2.__next__()

    print("%s开始准备做包子啦" % name)

    for i in range(6):

        print("第%d次做了%s个包子"%(i+1,len(food)))

        time.sleep(random.randint(1,3))

        f1 = food[i]

        c1.send(f1)

        food.append(f1)

        random.shuffle(food)

        c2.send(food[i])

        

producer('老子')

 

大儿子 准备吃包子啦!

小儿子 准备吃包子啦!

老子开始准备做包子啦

第1次做了6个包子

[韭菜鸡蛋]馅包子来了,被[大儿子]吃了!

[韭菜鸡蛋]馅包子来了,被[小儿子]吃了!

第2次做了7个包子

[韭菜鸡蛋]馅包子来了,被[大儿子]吃了!

[猪肉大葱]馅包子来了,被[小儿子]吃了!

第3次做了8个包子

[韭菜鸡蛋]馅包子来了,被[大儿子]吃了!

[猪肉大葱]馅包子来了,被[小儿子]吃了!

第4次做了9个包子

[猪肉白菜]馅包子来了,被[大儿子]吃了!

[羊肉白菜]馅包子来了,被[小儿子]吃了!

第5次做了10个包子

[虾仁海鲜]馅包子来了,被[大儿子]吃了!

[韭菜鸡蛋]馅包子来了,被[小儿子]吃了!

第6次做了11个包子

[韭菜鸡蛋]馅包子来了,被[大儿子]吃了!

[虾仁海鲜]馅包子来了,被[小儿子]吃了!

 

迭代器 

迭代器概述 

可以直接作用于for循环的数据类型有以下几种: 

一类是集合数据类型,如list,tuple,dict,set,str等一类是generator ,包括生成器和带yeild的generator function 

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

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

a = [i for i in range(10)]

next(a)

 

---------------------------------------------------------------------------

 

TypeError                                 Traceback (most recent call last)

 

<ipython-input-23-8981550fe3e0> in <module>

      1 a = [i for i in range(10)]

----> 2 next(a)

 

 

TypeError: 'list' object is not an iterator

 

list,dict,str虽然是Iterable,却不是Iterator 

from collections import Iterator

from collections import Iterable

print(isinstance(a,Iterator))

print(isinstance(a,Iterable))

print(isinstance({},Iterable))

print(isinstance('abc',Iterable))

 

False

True

True

True

 

生成器就是一个迭代器 

a = (i for i in range(10))

print(next(a))

print(isinstance(a,Iterator))

 

0

True

 

iter()函数 创建迭代器 

iter(iterable)#一个参数,要求参数为可迭代的类型 

把list、dict、str等Iterable变成Iterator可以使用iter()函数: 

print(isinstance({},Iterator))

print(isinstance('abc',Iterator))

print(isinstance(iter({}),Iterator))

print(isinstance(iter('abc'),Iterator))

 

False

False

True

True

 

你可能会问,为什么list、dict、str等数据类型不是Iterator? 

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。 

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。 

小结 

 凡是可作用于for循环的对象都是Iterable类型;  凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;  集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。  

Python的for循环本质上就是通过不断调用next()函数实现的,例如: 

for x in [1, 2, 3, 4, 5]:

    print(x,end=',')

 

1,2,3,4,5,

 

实际上完全等价于: 

# 首先获得Iterator对象:

it = iter([1, 2, 3, 4, 5])

# 循环:

while True:

    try:

        # 获得下一个值:

        x = next(it)

        print(x,end=',')

    except StopIteration:

        # 遇到StopIteration就退出循环

        break

 

 

1,2,3,4,5,

 

创建一个迭代器(类) 

把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。 

如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 __init__(), 它会在对象初始化的时候执行 

__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。 

from itertools import islice

class Fib:

    def __init__(self):

        self.prev = 0

        self.curr = 1

    def __iter__(self):

        return self

    def __next__(self):

        self.prev,self.curr = self.curr,self.prev+self.curr

        return self.curr

f = Fib()

print(list(islice(f ,0,10)))

 

[1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

 

Fib既是一个可迭代对象(因为它实现了 __iter__方法),又是一个迭代器(因为实现了 __next__方法) 

StopIteration 

StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。 

在 20 次迭代后停止执行: 

class MyNumbers:

    def __init__(self):

        self.a = 1

    

    def __iter__(self):

        return self

 

    def __next__(self):

        if self.a <= 20:

            x = self.a

            self.a += 1

            return x

        else:

            raise StopIteration

 

myclass = MyNumbers()

myiter = MyNumbers()

# myiter = iter(myclass)

 

for x in myiter:

    print(x,end=",")

 

 

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,

 

内置迭代器工具 

比如 itertools 函数返回的都是迭代器对象 

count无限迭代器 

from itertools import count

counter = count(start=10)  

print(next(counter))

print(next(counter)) #python内建函数next()对itertools创建的迭代器进行循环

 

10

11

 

cycle 无限迭代器,从一个有限序列中生成无限序列: 

from itertools import cycle

colors = cycle(['red','black','blue'])

print(next(colors))

print(next(colors))

print(next(colors))

print(next(colors))

print(next(colors))  

 

red

black

blue

red

black

 

itertools的子模块 islice 控制无限迭代器输出的方式 

islice的第二个参数控制何时停止迭代,迭代了11次后停止,从无限的序列中生成有限序列: 

from itertools import count

counter = count(start=10)

i=4

print(next(counter))

while i > 0:

    print(next(counter))

    i -= 1

 

10

11

12

13

14

 

from itertools import count

for i in count(10):

    if i > 14 :

        break

    else:

        print(i)

 

10

11

12

13

14

 

from itertools import islice

from itertools import count

for i in islice(count(10),5):

    print(i)

 

10

11

12

13

14

 

from itertools import cycle

from itertools import islice

colors = cycle(['red','black','blue'])

limited = islice(colors,0,4)

for x in limited:

    print(x)

 

red

black

blue

red

 

装饰器 

器,代表函数的意思 

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

每个人都有的内裤主要功能是用来遮羞,但是到了冬天它没法为我们防风御寒,咋办?我们想到的一个办法就是把内裤改造一下,让它变得更厚更长,这样一来,它不仅有遮羞功能,还能提供保暖,不过有个问题,这个内裤被我们改造成了长裤后,虽然还有遮羞功能,但本质上它不再是一条真正的内裤了。于是聪明的人们发明长裤,在不影响内裤的前提下,直接把长裤套在了内裤外面,这样内裤还是内裤,有了长裤后宝宝再也不冷了。装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。 

原则: 

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

实现装饰器知识储备: 

 1 函数即“”变量“”  2 高阶函数 a 把一个函数名当做实参传给另一个函数 b 返回值中包含函数名  

高阶函数 

import time

def bar():

    time.sleep(3)

    print('in the bar')

def test2(func):

    print(func)

    return func

 

print(test2(bar)) #调用test2,打印bar的内存地址,返回bar的内存地址,又打印

 

<function bar at 0x7fe03849e620>

<function bar at 0x7fe03849e620>

 

bar=test2(bar) # 返回的bar的内存地址,赋值给bar

bar() #run bar

 

<function bar at 0x7fe03849e620>

in the bar

 

嵌套函数 

x = 0

def grandpa():

    x = 1

    print(x)

    def dad():

        x =2

        print(x)

        def son():

            x =3

            print(x)

        son()

    dad()

 

grandpa()

 

1

2

3

 

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

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("the func run time is %s" %(stop_time-start_time))

    return deco

@timer #test1=timer(test1) 把deco的内存地址返回给test1

def test1():

    time.sleep(1)

    print('in the test1')

 

@timer # test2 = timer(test2) = deco test2(name) =deco(name)

def test2(name,age):

    print("test2:",name,age)

 

test1() #实际上是在执行deco

test2("alex",22)

 

in the test1

the func run time is 1.001246452331543

test2: alex 22

the func run time is 0.00011372566223144531

 

类装饰器 

没错,装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的__call__方法 

 

class Foo(object):

    def __init__(self, func):

        self._func = func

 

    def __call__(self):

        print ('class decorator runing')

        self._func()

        print ('class decorator ending')

 

@Foo

def bar():

    print ('bar')

bar()

 

 

class decorator runing

bar

class decorator ending

 

装饰器可以把与业务逻辑无关的代码抽离出来,让代码保持干净清爽,而且装饰器还能被多个地方重复利用。比如一个爬虫网页的函数,如果该 URL 曾经被爬过就直接从缓存中获取,否则爬下来之后加入到缓存,防止后续重复爬取。 

def web_lookup(url, saved={}):

    if url in saved:

        return saved[url]

    page = urllib.urlopen(url).read()

    saved[url] = page

    return page

 

pythonic 

import urllib.request as urllib # py3

def cache(func):

    saved= {}

    def wrapper(url):

        if url in saved:

            return saved [url]

        else:

            page = func(url)

            saved [url] = page

            return page

    return wrapper

    

@cache

def web_lookup(url):

    return urllib.urlopen(url).read()

 

用装饰器写代码表面上感觉代码量更多,但是它把缓存相关的逻辑抽离出来了,可以给更多的函数调用,这样总的代码量就会少很多,而且业务方法看起来简洁了。 

带参数的decorator 

def log(text):

    def decorator(func):

        def wrapper(*args, **kw):

            print('%s %s():' % (text, func.__name__))

            return func(*args, **kw)

        return wrapper

    return decorator

 

还差最后一步。因为我们讲了函数也是对象,它有__name__等属性,但你去看经过decorator装饰之后的函数,它们的__name__已经从原来的’now’变成了’wrapper’: 

@log('execute')

def now():

    print('2015-3-25')

    

now()

now.__name__

 

execute now():

2015-3-25

 

 

 

 

 

'wrapper'

 

因为返回的那个wrapper()函数名字就是’wrapper’,所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。 

不需要编写wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下: 

import functools

 

def log(text):

    def decorator(func):

        @functools.wraps(func)

        def wrapper(*args, **kw):

            print('%s %s():' % (text, func.__name__))

            return func(*args, **kw)

        return wrapper

    return decorator

 

 

@log('execute')

def now():

    print('2015-3-25')

    

now()

now.__name__

 

execute now():

2015-3-25

 

 

 

 

 

'now'

 

那么不带参数decorator,也是一样的 

import functools

 

def log(func):

    @functools.wraps(func)

    def wrapper(*args, **kw):

        print('call %s():' % func.__name__)

        return func(*args, **kw)

    return wrapper

 

实例—登录认证 

import functools

 

 

user,passwd = 'sun' ,'123'

def auth(auth_type):

    print("auth func:",auth_type)

    def decorator(func):

        @functools.wraps(func)

        def wrapper(*args,**kwargs):

            print('wrapper func args:',*args,**kwargs)

            if auth_type == 'local':

                username = input('Username:').strip()

                password = input("Password:").strip()

                if user == username and passwd == password:

                    print("\033[32;1mUser has passed authentication\033[0m")

                    res = func(*args, **kwargs) 

                    print("--after authentication--")

                    return res

                else:

                    exit("\033[31;1mInvalid username or password\033[0m")

            elif auth_type == 'ldap':

                res = func(*args, **kwargs)

                print("搞毛线ldap,不会。。。。")

                return res

 

        return wrapper

    return decorator

 

def index():

    print("welcome to index page")

 

@auth(auth_type='local')

def home():

    print("welcome to home page")

    return 'from home'

 

@auth(auth_type='ldap')

def bbs():

    print("welcome to bbs page")

 

 

index()

print(home())  #wrapper

bbs()

 

 

auth func: local

auth func: ldap

welcome to index page

wrapper func args:

Username:sun

Password:123

[32;1mUser has passed authentication[0m

welcome to home page

--after authentication--

from home

wrapper func args:

welcome to bbs page

搞毛线ldap,不会。。。。

总结

以上是生活随笔为你收集整理的[转载] python迭代器、生成器和装饰器的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。