Python进阶-三器一闭

Python进阶-三器一闭

  • 迭代器
  • 生成器
  • 闭包
  • 装饰器

迭代器

定义
 迭代器是一个可以记住遍历位置的对象,从第一个元素开始访问,知道所有元素被访问结束,迭代器只能向后遍历,不能后退
 一个实现了__iter__方法和__next__ 方法的对象就是迭代器
可迭代对象
 只要能通过for…in…进行遍历的,那么这个数据类型就是可迭代对象
 一个实现了__iter__方法的对象就是可迭代对象
注意
 迭代器一定是可迭代对象,可迭代对象不一定是迭代器
判断迭代器和可迭代对象
 通过Iterable来判断是否是可迭代对象

from collections.abc import Iterable
a = []
print(isinstance(a, Iterable))
# True

 通过Iterator来判断是否是迭代器

from collections import Iterator
t = []
print(isinstance(t,Iterator))
# False
t1 = iter(t)
print(isinstance(t1,Iterator))
# True

生成器

定义
 在Python中,一边循环一边计算的机制称为生成器(生成器是一种特殊的迭代器)
创建生成器的两种方式
 1.将列表推导式的[]换成()

[x for x in range(10)] ----> (x for x in range(10))

 2.函数中含有yield关键字

def num():
    num1 = 1
    num2 = 2
    while True:
        temp_num = num1
        num1, num2 = num2, num1 + num2
        yield temp_num

n = num()
print(next(n))
print(next(n))
print(next(n))
print(next(n))
print(next(n))
-------------执行结果--------------
1
2
3
5
8

生成器的调用方法
next():唤醒函数,从断点处继续执行
send():唤醒函数,并向断点处传入一个值并继续执行

生成器的特点(优势)
生成器存储的是生成数据的方式,并不是存储数据,因此节约内存

闭包

定义
 在函数内嵌套了另一个函数,内部函数用到了外部函数的局部变量,并且外部函数返回了内部函数的引用

def out_func(out_num):
	def in_func(in_num):
		return out_num + in_num
	return in_func


ret = out_func(10)
ret(20)  # 30

闭包和普通函数的区别
 普通函数执行结束后会被python解释器自动释放局部变量,闭包可以让参数和变量不被垃圾回收机制回收,始终保存在内存中

装饰器

定义
 能够快速将函数的指向修改, 在不修改代码的前提下,给函数添加功能的方式

实现过程
 将原函数的引用当做实参传递到闭包中;修改原函数的指向为闭包中的内部函数

**修饰无参函数

from time import ctime, sleep

# 定义一个闭包
def timefun(func):
    def wrapped_func():
        print("%s called at %s" % (func.__name__, ctime()))
        func()
    return wrapped_func


@timefun  # 使用装饰器对foo进行装饰,此时相当于foo = timefun(foo)
def foo():
    print("I am foo")

foo()  # 相当于调用的是wrapped_func函数
sleep(2)
foo()  # 相当于调用的是wrapped_func函数

修饰有参函数

from time import ctime, sleep

def timefun(func):
    def wrapped_func(a, b):
        print("%s called at %s" % (func.__name__, ctime()))
        print(a, b)
        func(a, b)
    return wrapped_func

@timefun
def foo(a, b):
    print(a+b)

foo(3,5)
sleep(2)
foo(2,4)

修饰不定长参数的函数

from time import ctime, sleep


def timefun(func):
    def wrapped_func(*args, **kwargs):
        # args=(3,5,7)
        # kwargs = {}
        print("%s called at %s"%(func.__name__, ctime()))
        func(*args, **kwargs)  # 对args,kwargs进行拆包,此时相当于func(3,5,7)
    return wrapped_func


@timefun
def foo(a, b, c):
    # a=3,b=5,c=7
    print(a+b+c)  # 15

foo(3,5,7)  # 将3,5,7这些未命名参数传递到第5行函数中,此时args用元组存储

多个装饰器装饰同一个函数

# 定义函数:完成包裹数据
def makeBold(fn):
    def wrapped():
        return "" + fn() + ""
    return wrapped

# 定义函数:完成包裹数据
def makeItalic(fn):
    def wrapped():
        return "" + fn() + ""
    return wrapped

@makeBold
def test1():
    return "hello world-1"

@makeItalic
def test2():
    return "hello world-2"

@makeBold
@makeItalic
def test3():
    return "hello world-3"

print(test1())
print(test2())
print(test3())

带参数的装饰器

import time


def call_out2(timeout=0):
    def call_out1(func):
        def call():
            print("----1----")
            time.sleep(timeout)
            ret = func()
            print("----2----")
            return ret
        return call
    return call_out1


# 下面的装饰过程
# 1. 调用timefun_arg("itcast") 得到一个返回值,即time_fun
# 3. 然后执行time_fun(foo) 得到一个返回值,即wrapped_func
# 4. 让foo = wrapped_fun,即foo现在指向wrapped_func
@call_out2(2)
def print_hello():
    print("hello world")
    return "ok"


print(print_hello())

使用类装饰

class Test(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s" % func.__name__)
        self.__func = func
    def __call__(self):
        print("---装饰器中的功能---")
        self.__func()


#说明:
#1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
#   并且会把test这个函数名当做参数传递到__init__方法中
#   即在__init__方法中的属性__func指向了test指向的函数
#2. test指向了用Test创建出来的实例对象
#3. 当在使用test()进行调用时,就相当于直接调用实例对象,因此会调用这个对象的__call__方法
#4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用
#   所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体
@Test
def test():
    print("----test---")


test()  # 如果把这句话注释,重新运行程序,依然会看到"--初始化--"

你可能感兴趣的:(python,python,生成器)