Python's three devices

First, the decorator
   closure function
   decorator Profile
   decorator template
   syntax sugar decorator
Second, the iterator
three generators

First, decorator

Closure function

Closed: it refers to a defined function within the function

Is a function such as mobile phones closure (inner function), is wrapped phone box (outer function),
the mobile phone can use something in the box, the inner layer name layer function can refer to the function.

Closure function : function defined within the function, and the function name of the external function comprises a reference field effect, the function is called closure function.

Closure nested function is a function, the function object, and the scope namespace combination.

基本形式:
def outer():
    name ='egon'
    def inner():
        print('my name is %s' %name)
    return inner
# print(outer())
inner=outer()  #实现了外部调用内部的函数
inner()
注意:作用域关系在函数定义阶段就定死了,与调用位置无关

Outside the closure function up to two sets of function enough

Decorative Introduction

: Tools
decoration: add new features to the object to be decorated

Decorator: Decorative tool

--- >> decorated objects need to add function function
decorator function --- >>

The role of decorator : the premise of decorative objects and invocation of the source code is not modified, adding new features to its
principles decorator must be followed: Open Closed Principle

Why use a decorator: code redundancy can solve problems and improve the scalability of the code

Open Closed Principle

Open: Adding on functional capabilities is open.
Closed: modifying the function function is closed.

Summarizes the following principles:

  1. Does not modify the source code of an object decorated
  2. It does not modify the object invocation modified

Objective: To extend new functions on the basis of 1 and 2 follow the principle of

模拟下载电影函数的运行时间

import time
def download_m():
    print('开始下载电影....')
    time.sleep(3)
    print('电影下载完成....')
#
# start_time = time.time()
# download_m()
# end_time = time.time()
# print(f'消耗时间:{end_time-start_time}')


def time_record():
    def inner():
        start_time = time.time()   #统计开始
        download_m()   #写死了,只能给download_m函数用
        end_time = time.time()
        print(f'消耗时间:{end_time-start_time}')   #结束统计,打印消耗时间
    return inner
func = time_record()    #返回的是inner的内存地址
func()    #调用的实质其实是inner函数
改进版
import time
def download_m():
    print('开始下载电影....')
    time.sleep(3)
    print('电影下载完成....')

# 添加时间功能
def time_record(func):    # func = download_m
    def inner():
        start_time = time.time()   #统计开始
       # download_m()   #写死了,只能给download_m函数用
        func()      # func() = download_m()
        end_time = time.time()
        print(f'消耗时间:{end_time-start_time}')   #结束统计,打印消耗时间
    return inner     #返回的是inner的内存地址
res = time_record(download_m)  #被装饰对象的调用方式
res()
问题1:被装饰对象,有返回值

def download_m():
    print('开始下载电影....')
    time.sleep(3)
    print('电影下载完成....')
    return "小丑.mp4"

def time_record(func):
    def inner():
        start_time = time.time()
        res = func()        # func() = download_m()
        end_time = time.time()
        print(f'消耗时间:{end_time-start_time}')
        return res       #res = download_m()
    return inner

download_m = time_record(download_m)   #  time_record(download_m)=inner#重新赋值给download_m
download_m()
问题2:被装饰对象,有参数

def download_m(url):
    print(f'{url}开始下载电影....')
    time.sleep(3)
    print('电影下载完成....')
    return"小泽.mp4"

def time_record(func):  # func <-- download_movie
    # url = 'https://www.baidu.com/'
    # 在闭包函数中
    def inner(url):
        start_time = time.time()
        res = func(url)  # func(url) ---> download_movie(url)
        end_time = time.time()
        print(f'消耗时间: {end_time - start_time}')
        return res
    return inner
download_m = time_record(download_m)
download_m('https://www.baidu.com')
问题3: 假如被装饰对象需要接收多个参数

def download_movie(url1,url2):
    print(f'{url1,url2}开始下载电影....')
    time.sleep(3)  # 等待3秒
    print('电影下载成功...')
    return '小泽.mp4'
#装饰器最终版本
def time_record(func):
    def inner(*args,**kwargs):    #*args,**kwargs接受所有的参数
        start_time = time.time()
        res = func(*args,**kwargs)  # 将被装饰对象需要接收的任意参数 原封不动传给func
        end_time = time.time()
        print(f'消耗时间: {end_time - start_time}')
        return res
    return inner
download_movie = time_record(download_movie)
download_movie(url1='https://www.baidu.com', url2='https://www.hao123.com')

Superposition decorator

叠加装饰器:
    在同一个被装饰对象中,添加多个装饰器,并执行。
    @装饰1
    @装饰2
    @装饰3
    def 被装饰对象():
        pass

    注意: 装饰器在调用被装饰对象时才会执行添加的功能。

    - 叠加装饰器:
        - 装饰的顺序: 由下到上装饰
        - 执行的顺序: 由上往下

 注意: 无论inner中出现任何判断,最后都要返回“调用后的被装饰对象” func(*args, **kwargs)

No reference decorator : when decorated decoration objects, did not pass the parameters decorator.
There are parameters decorator : essentially no arguments on the decorator cover an outer function, no parameters decorator can reference the name of the outer function.

Decorative template

def wrapper(func):
    def inner(*args, **kwargs):
    
        为被装饰对象添加新功能
        
        res = func(*args, **kwargs)  # 调用被装饰对象,得到返回值
        
        为被装饰对象添加新功能
        
        return res    
    return inner

def func1():
    pass

func1 = wrapper(func1)
func1()  # inner()

Syntactic sugar decorator

Decorator syntax sugar, belongs to the decorator.

@ : Decorator syntax sugar
Note: When using the decorator syntax sugar, decorators must be defined on the decorative objects.

import time

# 统计函数执行时间装饰器

def wrapper(func):  # 被装饰对象
    def inner(*args, **kwargs):  # 被装饰对象的参数
        start_time = time.time()          # 调用前增加新功能
        res = func(*args, **kwargs)         # 调用被装饰对象,并接收返回值
        end_time = time.time()           # 调用后添加新功能
        print(end_time - start_time)

        return res
    return inner
    
@wrapper  # download= wrapper(download_m)
def download_m()
     print('开始下载电影....')
     time.sleep(3)
     print('电影下载完成....')
download_m()

Second, the iterator

Definition: iteration value tool that can iterate values.
Iteration: repeat the iteration means, the result of each iteration is based on the results from the time
- iterables: All sequence types: list, tuple, dict, str , set, f ( file)

#依赖于索引取值
goods=['mac','lenovo','acer','dell','sony']

index=0
while index < len(goods):
    print(goods[index])
    index+=1
dict1 = {'name':'bob','age':18,'sex':'male'}
iter_dict1 = dict1.__iter__()    #iter_dict1是一个迭代器对象 
print(iter_dict1.__next__())
print(iter_dict1.__next__())
print(iter_dict1.__next__())
>>>name
>>>age
>>>male
补充:

list1 = ['tank', 'jason鸡哥', 'sean', '饼哥']
iter_list1 = list.__iter__()
while True:
    # 补充: try:获取异常
    try:
        print(iter_list1 = list.__iter__())   #报错
    #立即触发此代码 StopIteration
    except StopIteration
        break
凡是内部有.__iter__()方法的都是可迭代对象。

例如:
str='hello'
str1.__iter__()

-获取迭代器:
    通过可迭代对象.__iter__(),得到的返回值就是"迭代器对象

-如何迭代取值:
    迭代器对象.__next__(),每次执行,都会从迭代器对象中取出一个值
    
-迭代器对象的优点:
     1. 不依赖于索引迭代取值
     2. 节省内存空间。
 缺点:
     1.取指定某个值麻烦
     2.每次取值都要从第一个值开始,无法同过索引取值
     3.无法通过len()计算长度


        - 迭代器本质上是一个可迭代对象

        - 文件本质上既是迭代器对象,也是可迭代对象。

        - 可迭代对象不一定是迭代器对象


for循环原理:

for i in 可迭代对象:
    - in: 会将可迭代对象自动调用.__iter__()变成迭代器对象
     
    - for循环内置捕获异常机制
set1 = '1, 2, 3, 4'
iter_set1 = set1.__iter__()    #iter_set1 迭代器
print(iter_set1.__iter__() is iter_set1)  #True

list1 = [1, 2, 3, 4]
iter_list1 = list1.__iter__()
print(iter_list1 is list1)   #False

Third, the generator

What is a generator?

Generation tool
builder is a "custom" iterator, essentially an iterator

How to achieve Builder

Whenever contain keywords yield Inside the function, the function is called, the code will not execute the function body, but will return a result, which is a generator

-yield:
    只能在函数内部定义
    每次yield都会往生成器对象中添加一个值,
    yield可以保存函数的暂停状态


yield与return:
    相同点:
        返回值的个数都是无限制的。

    不同点:
        return只能返回一次值,yield可以返回多次值
# 自定义的迭代器:
def func():
    print('form func')
    yield 1
res = func()  #res是一个生成器
print(res)  #<generator object func at 0x0000016D5A0DEF48>


#当我们通过.__next__取值时,才会执行函数体代码。
def func():
    print('from func')
    yield 1
res = func()
print(res.__next__())


def func():
    print('开始准备下蛋')
    print('一个鸡蛋')
    yield '鸡蛋1'
    print('第二个鸡蛋')
    yield '鸡蛋2'
    print('第三个鸡蛋')
    yield '鸡蛋3'
    print('取最后一个鸡蛋,查看是否还有')
res = func()   #res是迭代器对象
# print(next(res))
# print(next(res))
# print(next(res))
# print(next(res)) #StopIteration 报错

迭代器对象.__next__() ==next(迭代器对象)
print(res.__next__())   #当我们通过.__next__取值时,才会执行函数体代码
print(res.__next__())
print(res.__next__())
print(res.__next__())   #StopIteration 报错

# 循环10次
for i in range(1,11):
    print(i)
  #  python2:range(1,5)--->[1,2,3,4]
  # python3:range(1,5) --->range对象 --->生成器 --->迭代器

#自定义range功能,创建一个自定义的生成器
def my_range(start,end,move):
    while start<end:
        yield start
        start +=move

g_range = my_range(1,5,2)   #g_range 是生成器
print(g_range)

Guess you like

Origin www.cnblogs.com/baohanblog/p/12143040.html