Python 迭代器 生成器 装饰器 上下文管理器

2020/9/14 5:03:58

本文主要是介绍Python 迭代器 生成器 装饰器 上下文管理器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

基本约定

ClsX: 类X
Valx: 变量x
Funcx: 函数x
Codex: 代码片段x

Python内部对象特殊方法/属性

1.__dict__属性:

ClsA.__dict__,类A的属性字典,包括
属性,https://www.cnblogs.com/alvin2010/p/9102344.html
ValA.__dict__, 变量X的属性字典

2.__getattr__(self, item):

# 获取名为item的属性
# 默认等同于:return self.__dict__[item]

3.__setattr__(self, item, value):

# 设置名为item的属性值为value
# 默认等同于:self.__dict__[item] = value



迭代器和生成器

迭代是Python中遍历访问集合元素的一种方式。

迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。

https://www.runoob.com/python...

# 假设有个方法,可以根据传入的ID,从服务器获取内容,返回为空的时候说明没有内容了

def get_data(rid):
    if rid > 5:
        return 
    return '数据%s' % rid

def get_data2(rid):
    if rid > 3:
        return
    return 'Data%s' % rid

# 现在我们需要遍历全部数据
i = 1
while True:
    data = get_data(i)
    if not data:
        break
    print(data)
    i += 1

i = 1
while True:
    data = get_data2(i)
    if not data:
        break
    print(data)
    i += 1

# 封装版本
def get_all(func):
    datas = []
    i = 1
    while True:
        data = func(i)
        if not data:
            break
        datas.append(data)
        i += 1
    return datas

for data in get_all(get_data):
    print(data)

# 生成器版本
def gen_all(func):
    i = 1
    while True:
        data = func(i)
        if not data:
            break
        yield data
        i += 1


for data in gen_all(func=get_data):
    print(data)

# 迭代器版本
class AllGetter:
    def __init__(self, func):
        self.func = func
        self.i = 1
    
    def __iter__(self):
        return self
 
    def __next__(self):
        data = self.func(self.i)
        if not data:
            raise StopIteration
        self.i += 1
        return data

x = (i for i in [1,2,3])
while True:
    print(x.__next__())
    

for data in AllGetter(func=get_data):
    print(data)


x = AllGetter(func=get_data)
for data in x:
    print(data)

#等同于

it = iter(x) # it = x.__iter__()
while True:
    print(next(it))

装饰器

# 假如我们需要统计某些函数func1、func2的执行时间
import time
def func1():
    time.sleep(1)

def func2():
    time.sleep(2)

t1 = time.time()
func1()
print('func1', time.time() - t1)

t2 = time.time()
func2()
print('func2', time.time() - t2)

# 这类问题可抽象为以下:
# Code1
# FuncX
# Code2


def func3(a, b):
    print('a+b', a+b)

# 定义函数的做法
def timeit(func, *args, **kwargs):
    t = time.time()
    func(*args, **kwargs)
    print(func.__name__, time.time() - t)

timeit(func1)
timeit(func2)
timeit(func3, 1,2)

def funcwrap(rawfunc):
    def _wrap(newfunc):
        newfunc.__name__ = rawfunc.__name__
        return newfunc
    return _wrap

# 装饰器写法
def timeit2(func):
    from functools import wraps
    def _func(*args, **kwargs):
        t = time.time()
        r = func(*args, **kwargs)
        print(func.__name__, time.time() - t)
        return r
    return _func

@timeit2
def func4():
    time.sleep(0.5)

# 装饰器左右类似

newfunc4 = timeit2(func4)
func4 = newfunc4
func4(1,2)


# 装饰器用于类

clzs = []

def addit(clz):
    clzs.append(clz)
    return clz

@addit
class A(object):
    pass

@addit
class B(object):
    pass
    
@addit
class C(object):
    pass

print(clzs)

# 带参数的装饰器

def asapi(logined):
    def _wrap(func):
        def _func(*args, **kwargs):
            if logined:
                print('err')
                return 
            r = func(*args, **kwargs)
            return r
        return _func
    return _wrap

@asapi(logined=True)
def fun6():
    print('xxx')

# 等同于

logined = asapi(logined=True)

@logined
def fun6():
    print('xxx')

上下文管理器

# 某些情况下,我们需要统计某段代码的执行时间
# 这类问题可抽象为以下:
# Code1
# CodeX
# Code2


import time


def func1():
    x = 2
    # 我们要统计下面这三行代码的执行时间
    a = 1
    b = a + x
    x = 4


# 一般做法
def func1():
    x = 2
    st = time.time()
    a = 1
    b = a + x
    x = 4
    print('cost time', time.time()-st)



# 上下文管理做法

class TimeIt(object):
    def __enter__(self):
        self.start = time.time()
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('time cost', time.time()-self.start)



def func1():
    x = 2
    with TimeIt():
        a = 1
        b = a + x
        x = 4

# 等同于
def func1():
    x = 2
    ti = TimeIt()
    ti.__enter__()
    a = 1
    b = a + x
    x = 4
    ti.__exit__(None,None,None)


# 和上下文环境进行交互

class TimeIt2(object):
    def __enter__(self):
        self.start = time.time()
        self._marks = []
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        for n, t in self._marks:
            print(n, t-self.start)
    
        print('time cost', time.time()-self.start)
    
    def mark(self, name):
        print('->', name, time.time() - self.start)
        self._marks.append((name, time.time()))


with TimeIt2() as t:
    time.sleep(2)
    t.mark('T1')
    time.sleep(1)
    t.mark('T2')
    time.sleep(0.5)

# 等同于
ti = TimeIt2()
t = ti.__enter__()
time.sleep(2)
t.mark('T1')
time.sleep(1)
t.mark('T2')
time.sleep(0.5)
ti.__exit__(None,None,None)


# 上下文交互2

class SendContext(object):
    def __init__(self, tag):
        self.tag = tag
    
    def __enter__(self):
        self.msglist = []
        return self.send
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(self.msglist)
    
    def send(self, userid):
        self.msglist.append(userid)
        

with SendContext('order') as send:
    for o in [1,2,3,4]:
        send(1)


这篇关于Python 迭代器 生成器 装饰器 上下文管理器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程