python中面向切片AOP编程之装饰器、迭代器、生成器

面向切片编程AOP之装饰器、迭代器、生成器


一、装饰器

装饰器的本质是闭包

闭包:(通常函数在调用完之后,函数内部定义的变量也销毁了)

作用:闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁

现实意义:闭包可以提高代码的复用性,不需要再手动定义额外的功能函数

注意点:由于闭包引用外部函数的变量,则外部函数的变量没有及时的释放,消耗内存

函数的嵌套、内部函数使用外部函数的变量、并且外部函数返回内部函数

def func_out(num1):
	#定义一个内部函数
	def func_inner(num2):
        #本意我们是想要修改我们的外部变量Num1的值,但实际上是在我们的内部函数中重新定义了一个据不变量
        #告诉解释器,此处用的是外部变量num1
        nonlocal num1 
        #并且重新定义外部变量的值
        num1 = 10
        result = num1+num2
        print("结果是:",result)
    return func_inner
#创建闭包实例  
#外层函数返回的是我们的内层函数
#所以执行闭包的时候传递进去的值是给了我们的内层函数
f = func_out(1)

#执行闭包。
#如果我们的内层函数存在返回值。则这里的闭包函数需要一个接收值
f(3)
f(4)

注意:

如果需要修改我们的外部函数的值,需要用到关键字nonlocal,并且进行重新的定义


 

装饰器:装饰器的本质就是一个闭包函数

功能特点:

  1. 不修改已有函数的源代码

  2. 不修改已有函数的调用方式

  3. 给已有函数增加额外的功能

 

实例:

def check(fn):
    print("装饰器函数执行了")

    def inner(num1,num2):#携带参数
        print("评论前请先登录。。。")
        fn(num1,num2)
    return inner

# 装饰器的执行时间是加载模块时立即执行
# 等价于comment = check(comment)
@check
def comment(a,b):
    print("发表评论")

comment(1,2)

#携带不定长参数:*args,**kwargs

运行结果:

[装饰器函数执行了]  外层装饰器函数

[评论前请先登录。。。]  内层装饰器函数

[发表评论]  被装饰函数


 

 

多个装饰器的使用

def make_div(func):
    """对被装饰的函数的返回值 div标签"""
    def inner():
        return "<div>" + func() + "</div>"
    return inner
​
​
def make_p(func):
    """对被装饰的函数的返回值 p标签"""
    def inner():
        return "<p>" + func() + "</p>"
    return inner
​
​
# 装饰过程: 1 content = make_p(content) 2 content = make_div(content)
# content = make_div(make_p(content))
@make_div
@make_p
def content():
    return "人生苦短"
​
result = content()
​
print(result)
​

 

#运行结果:
<div><p>人生苦短</p></div>
#多个装饰器可以对函数进行多个功能的装饰,装饰顺序是由内到外的进行装饰

总结:多个装饰器的装饰过程是: 离函数最近的装饰器先装饰,然后外面的装饰器再进行装饰,由内到外的装饰过程


 

带有参数的装饰器:

def logging(flag):
    #外部包装

    #内部装饰器
    def decorator(fn):
        def inner(num1, num2):
            #外部包装传递的参数进行判断
            if flag == "+":
                print("--正在努力加法计算")
            elif flag == "-":
                print("--正在努力减法计算")
            result = fn(num1, num2)
            return result

        return inner

    # 返回装饰器
    return decorator


# 使用装饰器装饰函数
@logging("+")
def add(a, b):
    result = a + b
    return result


@logging("-")
def sub(a, b):
    result = a - b
    return result


result = add(1, 2)
print(result)

result = sub(1, 2)
print(result)

 运行结果:

--正在努力加法计算
3
--正在努力减法计算
-1

总结:

 

使用带参数的装饰器,其实是在装饰器的外面又包裹了一个函数,使该函数接收参数,返回装饰器,因为@符号需要配合装饰器实例使用


 

类装饰器:

就是通过定义一个类来装饰函数

class Check(object):
    def __init__(self,fn):
        #初始化操作在此完成
        self.__fn = fn

    #实现__call__方法,表示对象是一个可调用对象,可以像调用函数一样进行调用
    def __call__(self, *args, **kwargs):
        #添加装饰功能
        print("请先登录")
        self.__fn()

@Check
def comment():
    print("发表评论")


comment()

运行结果:

请先登录
发表评论

代码说明:

  • @Check 等价于 comment = Check(comment), 所以需要提供一个init方法,并多增加一个fn参数。

  • 要想类的实例对象能够像函数一样调用,需要在类里面使用call方法,把类的实例变成可调用对象(callable),也就是说可以像调用函数一样进行调用。

  • call方法里进行对fn函数的装饰,可以添加额外的功能

总结:

1、想要让类的实例对象能够像函数一样进行调度,需要在类里面使用call方法,把类的实例变成可调用对象(callable)

2、类装饰器装饰函数功能在call方法里面进行添加

 


二、迭代器

1、通过iter()方法获得list的迭代对象,然后就可以通过next()方法来访问list中的元素了。当容器中没有可访问的元素后,next()方法将会抛出一个StopIteration异常终止迭代器。字符串,列表元组对象都可用于创建迭代器:

2、不过迭代器是有先知的,例如

  • 不能回到开始

  • 也无法复制一个迭代器

  • 因此要再次进行迭代只能重新生成一个新的迭代对象

3、iter()和next()方法,这俩个方法是迭代器最基本的方法

一个用来获取迭代对象

一个用来获取容器中的下一个元素

#iter方法和next方法的应用
list1 = [12,56,78,49,67,87]

it = iter(list1)
print(type(it))
#第一种方法
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
print(it.__next__())
#访问的元素超出list1时抛出StopIteration异常
#第二种方法
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))

运行结果:

<class 'list_iterator'>

12
56
78
49
67
87
Traceback (most recent call last):
    print(it.__next__())
StopIteration

自定义迭代器:

class MyIterration(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 val
        else:
            raise StopIteration()
ite = MyIterration(3)
print(next(ite))
print(next(ite))
print(next(ite))
# print(next(ite))

 理解后可以尝试写一下列表,元组,字典的迭代器,其实都是差不多的


生成器

是一种特殊的迭代器

如果列表的元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间

在python中,这样一边循环一边计算的机制,称之为生成器

# 生成式就是将列表推导式的[]换成()就可以了

g = (x + x for x in range(10))
print(g)
print(next(g))
print(next(g))
print(next(g))

for n in g:
    print(n)

# 示例代码
# 生成器函数的使用==斐波那契数列
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'


a = fib(10)
print(fib(10))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))

学习笔记整理(1) 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值