装饰器和迭代器

装饰器

一.装饰器简介

在不更改原功能函数内部代码,并且不改变调用方法的情况下为原代码扩展新的功能

二.闭包

一.什么是闭包?

闭包 = 函数 + 一个封闭的作用域

二.什么是封闭的作用域?

外部无法修改的作用域

封闭作用域----->闭包函数外层的作用域

三.闭包函数有什么特性

1、函数嵌套函数

2、外层函数return返回的是 内层函数

3、内层函数引用外部的非全局变量

四.例如

def a(func):
    @wraps(func)
    def aa(*args, **kwargs):
        print('前置')
        function = func(*args, **kwargs)
        function.age = 12
        print('后置')
        return function.__dict__

    return aa

三.函数装饰器的用法

1.装饰单个函数

def one():
    print("我是one函数")


def two(fun):
    print("开始运行befor")
    fun()
    print("结束运行after")


two(one)

在使用装饰器前首先需要明白函数可以通过参数的形式去传递。上面代码中two函数就是一个简单的装饰器,

fun参数表示的是修饰的函数

2.修饰单个带参函数

def two(fun):
    def three(*args, **kwargs):
        print("开始运行befor")
        fun(*args, **kwargs)
        print("结束运行after")
    return three


def one(name):
    print("我是log函数")


one = two(one)
one("李明")

two函数中返回的是three,在one=twp(one),也就相当于one为three函数来运行。这里简单介绍下*args,**kwargs作用。

*args:在运行函数传参时不确定传几个参数,可用*占位来代替未知数量参数

def one(*args, **kwargs):#args类型为元组
    for i in args:
        print(i)


one("李明", "王二", "张三")

**kwargs:当传入的是键值对格式的时候,可用kwargs

def one(*args, **kwargs):#kwargs为字典类型
    for k, v in kwargs.items():
        print("k", k, "v", v)


one(name="李明", age=12, sex="")

3.@键的使用

def two(fun):
    def three(*args, **kwargs):
        print("开始运行befor")
        fun(*args, **kwargs)
        print("结束运行after")

    return three


@two
def one(name):
    print("我是log函数")


one("li")

我们可以看出,在被修饰的函数前加上@装饰器,可实现同样的效果,@two就相当于one=two(one)

4.带参的装饰器

def two_01(name):
    def two(fun):
        def three(*args, **kwargs):
            print("开始运行befor")
            fun(*args, **kwargs)
            print("结束运行after")

        return three
    return two


@two_01("这里传入个参数即可")
def one():
    print("我是log函数")


one()

二.类装饰器的用法

1.带参的函数

class one:
    def __init__(self, fun):
        self.fun = fun

    def __call__(self, *args, **kwargs):
        print("开始执行前置")
        self.fun()
        print("开始执行结尾")


@one
def two():
    print("我是非常复杂的程序")

two()

类装饰器中有两个函数init初始化,和call把类变成一个可调用的对象

2.带有参数的类装饰器

class one:
    def __init__(self, name):
        self.name = name

    def __call__(self, fun):
        def one_01():
            print("开始执行前置")
            fun()
            print("开始执行结尾")

        return one_01


@one("李明")
def two():
    print("我是非常复杂的程序")


two()

此时接收被装饰的函数就是call,

3.被装饰带参的类

def a(func):
    @wraps(func)
    def aa(*args, **kwargs):
        print('前置')
        function = func(*args, **kwargs)
        function.age = 12
        print('后置')
        return function.__dict__

    return aa


@a
class ClaB:
    def __init__(self, name):
        self.name = name


b = ClaB('里面')
print(b)

1.可以再装饰器中定义被装饰器的属性字段

funcuion.age=12

2.@wraps()作用:将被装饰的函数的特殊属性保存到装饰器函数上,如:('__module__', '__name__', '__qualname__', '__doc__','__annotations__')

若没有wraps,那么在aa中打印print(aa.__name__)为aa,而不是被装饰的函数昵称

迭代器

迭代器有两个重要的方法iter和next,下面看下具体的用法

str = "1234"
str = iter(str) #定义一个迭代器
print(next(str))#next为迭代下一个
print(next(str))
print(next(str))

其实除了iter()和next()外,for循环也可遍历

str = "1234"
for i in str:
    print(i)

如何判断一个对象是否可迭代呢::isinstance()方法

from collections import Iterable
str = "1234"
print(isinstance(str,Iterable))

isinstance()里有两个参数,可判断两种参数类型是否相等,相等的话返回True,否则返回false

 

posted @ 2022-06-13 22:52  余生没有余生  阅读(145)  评论(0)    收藏  举报