迭代器生成器装饰器

1. 迭代器

1.1 什么是迭代器(iter)

1)迭代器是容器;程序中无法直接创建一个迭代器,只能将别的序列转换成迭代器。

2)特点:打印迭代器无法查看所有的元素、也无法获取元素的个数;获取元素的时候每次只能获取最前面的元素,而且元素取一个就少一个。

i1 = iter('abc123')
print(i1)     # <str_iterator object at 0x000001E2A9C78460>
# print(len(i1))    # 报错!

i2 = iter([10,20,30])
print(i2)     # <list_iterator object at 0x000002B0673966A0>

i3 = iter({'a':10,'b':20,'c':30})
print(i3)      # <dict_keyiterator object at 0x000002B0673BAA90>

1.2 查(获取元素)

迭代器不管以什么样的方式获取到了某个元素,那么这个元素一定会从迭代器中消失。

1.2.1 查单个

next(迭代器):获取迭代器中最前面的那个元素。

print(next(i1))   # a
print(next(i1))   # b

print(next(i2))   # 10
print(next(i2))   # 20
print(next(i2))   # 30
# print(next(i2))   # 报错!StopIteration停止迭代

print(next(i3))    # a

print(list(i1))    # ['c', '1', '2', '3']
print(list(i2))    # []
print(list(i3))    # ['b', 'c']
# print(next(i3))    # 报错!StopIteration
1.2.2 遍历
i4 = iter('hello')
for x in i4:
    print('x:',x)

# print(next(i4))   # 报错!StopIteration

2. 生成器

2.1 什么是生成器

1)生成器也是容器,其他容器是直接保存多个数据,生成器保存的是产生多个数据的算法。

2)生成器获取数据的方式和特点和迭代器一样。

2.2 创建生成器

调用一个带有yield关键字的函数就可以得到一个生成器对象。

def func1():
    print('+++')
    print('===')
    yield
    return 100


gen1 = func1()
print('result:',gen1)    # <generator object func1 at 0x00000215E5C0B900>  生成器对象

2.3 控制生成器产生数据的个数和值

1)一个生成器产生的数据的个数和值由创建生成器调用的那个函数的函数体在执行的时候会遇到几次yield以及每次yield后面的值决定。

a. 个数:由遇到的yield的次数决定;

b. 值:由yield后面的数据决定

def create1():
    yield 100
    yield 200
    yield 300
    

gen2 = create1()
# print(list(gen2))    # [100, 200, 300]
print(next(gen2))      # 100
print(next(gen2))      # 200
print(next(gen2))      # 300
# print(next(gen2))    # 报错!StopIteration


def create2():
    x = 0
    while True:
        yield x
        x += 1


gen3 = create2()
print(next(gen3))

for _ in range(100):
    print(next(gen3))

print(next(gen1))

练习:写一个生成器可以创建某个Python班级学生的学号,学号的范围是:python0001 ~ python1000。

def study_id(subject):
    for x in range(1,1001):
        yield f'{subject}{x:0>4}'


python_id = study_id('python')
java_id = study_id('java')
print(next(python_id))
print(next(java_id))
print(next(python_id))
print(next(java_id))

2.4 生成器创建数据的原理

每次获取生成器的数据的时候,就会去执行创建这个生成器的函数体,但是每次执行都只会执行到也iyield就停下来。

def func2():
    print('======')
    yield 100
    print('------')
    yield 200
    print('++++++')
    yield 300

gen4 = func2()
print('1.:',next(gen4))
print('2.:',next(gen4))
print('3.:',next(gen4))

3. 装饰器

3.1 什么是装饰器

1)装饰器是给已经定义好的函数添加功能的工具。

2)装饰器就是一个函数,这个函数既是实参高阶函数,又是返回值高阶函数。

3.2 给函数添加功能

练习:给函数添加功能,统计函数的执行时间。

# 解决方案1:直接修改原函数
def hello():
    # start = time.time()
    print('hello world!')
    # end = time.time()
    # print(f'总时间:{end - start}')


hello()


def factorial(n):
    # start = time.time()
    s = 1
    for x in range(1,n+1):
        s *= x
    print(s)
    # end = time.time()
    # print(f'总时间:{end - start}')


factorial(10)


# # 解决方案2:
# def total_time(fn,*args,**kwargs):
#     start = time.time()
#     fn(*args,**kwargs)
#     end = time.time()
#     print(f'总时间:{end - start}')
#
#
# total_time(hello)
# total_time(factorial,5)

# 解决方案3:
def total_time(fn):
    def new_fn(*args,**kwargs):
        start = time.time()
        result = fn(*args,**kwargs)
        end = time.time()
        print(f'总时间:{end - start}')
        return result
    return new_fn


@total_time
def hello():
    print('hello world!')


@total_time
def factorial(n):
    s = 1
    for x in range(1,n+1):
        s *= x
    print(s)

hello()
factorial(5)

4. 无参装饰器

4.1 无参装饰器语法

'''
语法:
def 装饰器名(原函数):
    def 添加完功能的新函数(*args,**kwargs):
        调用原函数
        添加新功能
    return 添加完功能的新函数

语法细化:
def 装饰器名(f):
    def new_f(*args,**kwargs):
        result = f(*args,**kwargs)
        新增功能
        return result
    return new_f

装饰器名 - 根据新增的功能来命名
'''
4.1.1 练习

练习1:写一个装饰器,在函数调用之前打印’千锋教育欢迎您!’

def add_tag(f):
    def new_f(*args,**kwargs):
        print('千锋教育欢迎您!')
        result = f(*args,**kwargs)
        return result
    return new_f


@add_tag    # hello = add_tag(hello)
def hello():
    print('hello world!')

练习2:写一个装饰器在函数调用结束的时候打印’end

def add_end(f):
    def new_f(*args,**kwargs):
        result = f(*args,**kwargs)
        print('====end====')
        return result
    return new_f


@add_end
def hello():
    print('hello world!')


hello()

练习3:写一个装饰器将返回值是数字的函数的返回值变成原来返回值的100倍。 3 -> 300; ‘abc’ -> ‘abc’; 1.23 -> 123。

def return_value(f):
    def new_f(*args,**kwargs):
        result = f(*args,**kwargs)
        if type(result) in (int,float):
            return result * 100
        return result
    return new_f

print(sum2(2,1))    # 300

5. 有参装饰器

5.1 有参装饰器语法

'''
有参装饰器语法细化:
def 装饰器名称(参数列表):
    def 无参装饰器(f):
        def new_f(*args,**kwargs):
            result = f(*args,**kwargs)
            新增功能
            return result
        return new_f
    return 无参装饰器


参数列表  -  看实现装饰器新增功能需不需要额外的数据,需要几个

'''
5.1.1 练习

练习1:写一个装饰器将返回值是数字的函数的返回值变成原来返回值的指定倍数。

def magnify(n):
    def temp(f):
        def new_f(*args,**kwargs):
            result = f(*args,**kwargs)
            if type(result) in (int,float):
                return result * n
            return result
        return new_f
    return temp


@magnify(300)
def sum2(num1,num2):
    return num1 + num2

print(sum2(1,2))

练习2:写一个装饰器,用法如下:

没有装饰器返回值如果是: 100 @tag§ -> ‘

100

def tag(n):
    def temp(f):
        def new_f(*args,**kwargs):
            result = f(*args,**kwargs)
            return f'<{n}>{result}</{n}>'
        return new_f
    return temp


@tag('a')
def sum2(num1,num2):
    return num1 + num2

print(sum2(40,60))

练习3:写一个装饰器(针对返回值是数字的函数),用法如下:

12 -> @operation(‘+’, 100) -> 112

12 -> @operation(‘-’, 20) -> -8

12 -> @operation(‘*’, 3) -> 36

12 -> @operation(‘/’, 3) -> 4.0

def operation(n1,n2):
    def temp(f):
        def new_f(*args,**kwargs):
            result = f(*args,**kwargs)
            return eval(str(result) + n1 + n2)
        return new_f
    return temp


@operation('/','100')
def sum2(num1,num2):
    return num1 + num2

print(sum2(40,60))
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值