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

一、装饰器

 装饰器可以使函数执行前和执行后分别执行其他的附加功能,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),装饰器的功能非常强大。装饰器一般接受一个函数对象作为参数,以对其进行增强 ,相当于C++中的构造函数,与析构函数。

特点:

  • 装饰器本身是一个函数,用于装饰其他函数。
  • 装饰器是一个闭包函数是嵌套函数,通过外层函数提供嵌套函数的环境。
  • 装饰器在权限控制,增加额外功能如日志,发送邮件用的比较多。

1,原函数不带参数的装饰器

 假设:我定义了一个函数lyshark,现在想要在不改变原来函数定义的情况下,在函数运行前打印一段话,函数运行后打印另一段话,要实现这样一个功能该怎么实现?看以下实现方式:

>>> import os
>>> import sys
>>> 
>>> def outer(function):
    def inner():
        print("主函数执行前,应先执行我!")
        result=function()
        print("主函数执行后,要执行我!")
        return result
    return inner

# (1) @ + 函数名 直接作用在需要装饰的函数上一行
# (2)自动执行outer函数并且将下面的函数名lyshark()当做参数传递到outer()
# (3)将outer函数的返回值inner,重新赋值给lyshark()函数
>>> @outer

def lyshark():
    print("lyshark 的主函数体,装饰器在装饰我(*^_^*)")
    return "lyshark 返回了"

>>> ret=lyshark()
主函数执行前,应先执行我!
lyshark 的主函数体,装饰器在装饰我(*^_^*)
主函数执行后,要执行我!
>>> 
>>> print("lyshark()函数的返回值: ",ret)
lyshark()函数的返回值:  lyshark 返回了
>>> 

2,原函数带一个参数的装饰器

假设:我们在前面的基础上给函数传递一个参数看看,它有啥反应,刺激一下它

>>> import os
>>> import sys
>>> 
>>> def outer(function):
    def inner(args):
        print("主函数执行前,应先执行我!")
        ret=function(args)
        print("主函数执行后,要执行我!")
        return ret
    return inner

>>> @outer

def lyshark(args):
    print(args)
    return "lyshark 返回了"

>>> 
>>> ret=lyshark("hello world!")
主函数执行前,应先执行我!
hello world!
主函数执行后,要执行我!
>>> 
>>> print("lyshark 的返回值是:",ret)
lyshark() 函数的返回值是: lyshark 返回了
>>> 
>>> 

3,原函数带两个参数的装饰器

 假设:我们在前面的基础上给函数传递两个参数看看,它有啥反应,刺激一下它

>>> import os
>>> import sys
>>> 
>>> 
>>> def outer(function):
    def inner(x,y):
        print("主函数执行前,应先执行我!")
        ret=function(x,y)
        print("主函数执行后,要执行我!")
        return ret
    return inner

>>> @outer

def lyshark(x,y):
    print(x,y)
    return "lyshark 返回了"

>>> 
>>> ret=lyshark("Hello","LyShark")
主函数执行前,应先执行我!
Hello LyShark
主函数执行后,要执行我!
>>> 
>>> print("lyshark() 函数的返回值是:",ret)
lyshark() 函数的返回值是: lyshark 返回了
>>> 
>>> 

4,传递一个万能参数

>>> import os
>>> import sys
>>> 
>>> def outer(function):
    def inner(*args,**kwargs):
        print("主函数执行前,应先执行我!")
        ret=function(*args,**kwargs)
        print("主函数执行后,要执行我!")
        return ret
    return inner

>>> 
>>> @outer

def lyshark(*args):
    print(args)
    return "lyshark 返回了"

>>> 
>>> num=[1,2,3,4,5]
>>> ret=lyshark(num)
主函数执行前,应先执行我!
([1, 2, 3, 4, 5],)
主函数执行后,要执行我!
>>> 
>>> print("lyshark() 函数的返回值是:",ret)
lyshark() 函数的返回值是: lyshark 返回了
>>> 
>>> 

5,一次使用两个装饰器装饰函数

如果一个装饰器不够用的话,我们可以使用两个装饰器,首先将函数与内层装饰器结合然后在与外层装饰器相结合,要理解使用@语法的时候到底执行了什么,是理解装饰器的关键。

>>> import os
>>> import sys
>>> 
>>> def outer2(function2):
    def inner2(*args,**kwargs):
        print("装饰器2,【开始】")
        ret=function2(*args,**kwargs)
        print("装饰器2,【结束】")
        return ret
    return inner2

>>> def outer1(function1):
    def inner1(*args,**kwargs):
        print("装饰器1,【开始】")
        ret=function1(*args,**kwargs)
        print("装饰器1,【结束】")
        return ret
    return inner1

>>> 
>>> @outer2
@outer1

def lyshark():
    print("lyshark 函数执行了!")

    
>>> lyshark()
装饰器2,【开始】
装饰器1,【开始】
lyshark 函数执行了!
装饰器1,【结束】
装饰器2,【结束】
>>> 

6,给装饰器添加参数

 前面的例子中,装饰器本身没有带参数,如果要写一个带参数的装饰器怎么办,下面我们就实现一个三层的装饰器。

>>> import functools
>>> import sys
>>> 
>>> def lyshark(temp=""):                                   #指定装饰器默认参数
    def decorator(function):
        @functools.wraps(function)                          #使被装饰的装饰器的函数名不改变
        def wrapper(*args,**kwargs):
            print("主函数执行前,应先执行我!")
            print("{}:{}".format(temp,function.__name__))   #这里调用了装饰器temp变量
            ret=function(*args,**kwargs)
            print("主函数执行后,要执行我!")
            return ret
        return wrapper
    return decorator

>>> #如果不给装饰器加参数,那么这个装饰器将使用默认参数 temp=" "
>>> @lyshark()
def test(x):
    print(x+100)

    
>>> test(100)
主函数执行前,应先执行我!
:test
200
主函数执行后,要执行我!
>>> 
>>> #下面是给装饰器一个参数,将不是用默认参数 temp=" "将变成 temp="LyShark" >>> @lyshark("LyShark") def test(x): print(x+100) >>> test(100) 主函数执行前,应先执行我! LyShark:test 200 主函数执行后,要执行我! >>>
>>> import sys
>>> import os
>>> 
>>> def lyshark(x="Hello",y="LyShark"):
    def decorator(function):
        def wrapper():
            print("主函数执行前,应先执行我!")
            print(x,y)
            ret=function()
            print("主函数执行后,要执行我!")
            return ret
        return wrapper
    return decorator

>>> 
>>> #使用默认参数的装饰器 : 此时 x="Hello" y="LyShark"
>>> @lyshark()
def test():
    print("我是test(),主函数,装饰器在装饰我")

    
>>> test()
主函数执行前,应先执行我!
Hello LyShark
我是test(),主函数,装饰器在装饰我
主函数执行后,要执行我!
>>> 
>>> #给装饰器指定参数 : 此时 x="My Name Is :" y="LyShark"
>>> 
>>> @lyshark("My Name Is :","LyShark")
def test():
    print("我是test(),主函数,装饰器在装饰我")

    
>>> test()
主函数执行前,应先执行我!
My Name Is : LyShark
我是test(),主函数,装饰器在装饰我
主函数执行后,要执行我!
>>> 

  

小总结

#使用装饰器函数实现,记录登陆状态 

import os
import sys

user_info={}

def check_login(func):
    def inner():
        if ((user_info.get("is_login",None) == True) and (user_info.get("user_type",None) == 0)):
            print("\n\n\n尊敬的LyShark,您好 \n\n\n")
            #ret=func()
            #return ret
        else:
            print("\n\n\n您没有登陆,请登录!!!\n\n")

    return inner
def root_login():
    user=input("输入用户名: ")
    if (user == "lyshark"):
        passwd=input("输入密码: ")
        if (passwd == "123123"):
            user_info["is_login"]=True
            user_info["user_type"]=0
            print("登陆成功,您的登陆状态已被记录!\n\n")
        else:
            print("您输入的密码不正确!\n\n")
    else:
        print("您输入的用户名不正确!\n\n")

@check_login
def user_index():
    print("index")


def main():
    while True:
        temp=input("1.用户登录  2.查看信息 \n LyShark --> ")
        if (temp =="1"):
            root_login()
        elif (temp =="2"):
            user_index()
        else:
            continue

main()
USER_INFO = {}

def check_login(func):
    def inner(*args,**kwargs):
        if USER_INFO.get('is_login',None):
            ret = func()
            return ret
        else:
            print("请登录")
    return inner

def check_admin(func):
    def inner(*args,**kwargs):
        if USER_INFO.get('user_type',None) == 2:
            ret = func()
            return ret
        else:
            print("无权限查看")
    return inner


@check_login         #先检查你是不是登陆了
@check_admin        #在检查你是不是管理员     路子很野啊,小伙子!!
def index():
    """
    管理员用户
    """
    print('index')

@check_login
def home():
    """
    普通用户
    
    """
    print('home')

def login():
    user = input("请输入用户名:")
    if user == 'admin':
        USER_INFO['is_login'] = True
        USER_INFO['user_type'] = 2
    else:
        USER_INFO['is_login'] = True
        USER_INFO['user_type'] = 1


def main():
    while True:
        inp = input('1、登录;2、查看信息;3、超级管理员管理\n>:')
        if inp == '1':
            login()
        elif inp == '2':
            home()
        elif inp == '3':
            index()


main()
View Code

二、生成器

  •  跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
  • 在 Python 中,使用了 yield 的函数被称为生成器(generator)。
  • 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
  • 调用一个生成器函数,返回的是一个迭代器对象。

生成器的一些例子

【实例】

#一个最简单的生成器

>>> import sys
>>> 
>>> def function():                #此函数就是一个生成器函数
    yield 1
    yield 2
    yield 3
    yield 4
    yield 5

    
>>> temp=function()                #实例化
>>> 
>>> temp.__next__()                #开始迭代
1
>>> temp.__next__()
2
>>> temp.__next__()
3
>>> temp.__next__()
4
>>> temp.__next__()
5
>>> 

#使用while循环构建一个生成器,并通过for遍历

>>> import sys
>>> 
>>> def yieldNum(x):
    y=0
    while (y <= x):
        yield y
        y += 1

        
>>> yie=yieldNum(4)
>>> 
>>> next(yie)
0
>>> 
>>> for i in yie:
    print(i)

    
1
2
3
4
>>> 

#使用生成器求1-10的平方

>>> def yieldNum():
    x=1
    while (x <=10 ):
        yield x ** 2
        x += 1

        
>>> yie=yieldNum()
>>> 
>>> for i in yie:
    print(i)

    
1
4
9
16
25
36
49
64
81
100
>>> 

#使用生成器自定义range函数

>>> def xrange(num):
    temp=-1
    while True:
        temp=temp+1
        if (temp >= num):
            return
        else:
            yield temp

            
>>> xrange(10)
<generator object xrange at 0x038E3030>

#生成器求斐波那契数列

>>> def fib(max):
    n,a,b=0,0,1
    while n < max:
        yield b
        a,b=b,a+b
        n+=1
    return "done"

>>> 
>>> 
>>> f=fib(5)
>>> 
>>> f
<generator object fib at 0x038F4A20>

 

列表解析

列表解析是python迭代机制的一种应用,它常用于实现创建新的列表,因此要放置于[]中

【实例】

>>> temp=[1,2,3,4]
>>> 
>>> temp1=[ x ** 2 for x in temp ]
>>> temp
[1, 2, 3, 4]
>>> temp1
[1, 4, 9, 16]
>>> temp
[1, 2, 3, 4]
>>> 
>>> temp1=[ x**2 for x in temp if x >=2 ]
>>> temp1
[4, 9, 16]
>>> 
>>> temp
[1, 2, 3, 4]
>>> 
>>> temp1=[ (i**2)/2 for i in range(1,10) ]
>>> temp1
[0.5, 2.0, 4.5, 8.0, 12.5, 18.0, 24.5, 32.0, 40.5]
>>> 
>>> temp1=["x","y","z"]
>>> temp2=[1,2,3]
>>> temp3=[ (i,j) for i in temp1 for j in temp2 ]
>>> temp3
[('x', 1), ('x', 2), ('x', 3), ('y', 1), ('y', 2), ('y', 3), ('z', 1), ('z', 2), ('z', 3)]
>>> 
>>> import os
>>> 
>>> file_list=os.listdir("/var/log")
>>> file_log=[ i for i in file_list if i.endswith(".log") ]
>>> print(file_log)
['boot.log', 'yum.log', 'ecs_network_optimization.log', 'ntp.log']
>>> 
>>> 
>>> file_log=[ i for i in os.listdir("/var/log") if i.endswith(".log") ]
>>> print(file_log)
['boot.log', 'yum.log', 'ecs_network_optimization.log', 'ntp.log']
>>> 

生成器表达式

生成器表达式并不真正创建数字列表,而是返回一个生成器对象,此对象在每次计算出一个条目后,把这个条目“产生”(yield)出来
生成器表达式使用了"惰性计算"或称作"延迟求值"的机制
序列过长,并且每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析

>>> import sys
>>> 
>>> yie=( i**2 for i in range(1,10) )
>>> next(yie)
1
>>> next(yie)
4
>>> next(yie)
9
>>> 
>>> for j in ( i**2 for i in range(1,10)):print(j/2)
... 
0.5
2.0
4.5
8.0
12.5
18.0
24.5
32.0
40.5
>>> 

三、迭代器

迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G文件的遍历。

特点:

  • 迭代是Python最强大的功能之一,是访问集合元素的一种方式。
  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
  • 迭代器是一个可以记住遍历的位置的对象。
  • 迭代器有两个基本的方法:iter() 和 next()
  • 字符串,列表或元组对象都可用于创建迭代器。
  • 迭代器便于循环比较大的数据集合,节省了内存开支。
  • 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容。
  • next()就相当于调用__next__(),for也是iterable(可迭代)对象。

迭代器的基本用法

>>> import sys
>>> 
>>> temp=iter([1,2,3,4,5,6,7,8,9])
>>> 
>>> temp
<list_iterator object at 0x03BD1F90>
>>> temp.__next__()
1
>>> temp.__next__()
2
>>> temp.__next__()
3
>>> 

或者

>>> import sys
>>> 
>>> temp=[1,2,3,4,5]
>>> 
>>> ite=temp.__iter__()
>>> 
>>> print(type(temp),type(ite))
<class 'list'> <class 'list_iterator'>
>>> 
>>> next(ite)
1
>>> 
>>> next(ite)
2
>>> next(ite)
3
>>> next(ite)
4
>>>

 迭代的另一种遍历方式

>>> ite=iter([1,2,3,4,5])
>>> 
>>> while True:
    try:
        temp=next(ite)
        print(temp)
    except StopIteration:
        break

    
1
2
3
4
5

参考文献:https://www.runoob.com/

参考文献:https://www.cnblogs.com/

猜你喜欢

转载自www.cnblogs.com/LyShark/p/9139266.html