python——迭代器,生成器,装饰器

迭代器:

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

创建迭代器:

     把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

     __iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。__next__() 方法会返回下一个迭代器对象。

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self
 
  def __next__(self):
    if self.a<=5:
        x = self.a
        self.a += 1
        return x
    else:
        raise StopIteration

 使用迭代器:

# 实例化
myclass = MyNumbers()
# iter声明迭代器
myiter = iter(myclass)
# next让迭代器迭代
print(next(myiter))
# 用for遍历迭代器,StopIteration会让for停止遍历
for i in myiter:
    print(i)

生成器:

     使用了 yield 的函数被称为生成器(generator)。
     跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 
     在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
     调用一个生成器函数,返回的是一个迭代器对象。    

创建使用生成器:

# 列表生成式
lis = [x*x for x in range(10)]
print(lis)
# 生成器表达式
# 把列表生成器的[]换成()就是生成器
generator_ex = (x*x for x in range(10))
print(generator_ex)
 
结果:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x000002A4CBF9EBA0>
# 生成器函数
def fib(max):
    n,a,b =0,0,1
    while n < max:
        yield b
        a,b =b,a+b
        n = n+1
    return 'done'
g = fib(6)
while True:
    try:
        x = next(g)
        print('generator: ',x)
    except StopIteration as e:
        print("生成器返回值:",e.value)
        break
for i in g:
    print(i)


generator:  1
generator:  1
generator:  2
generator:  3
generator:  5
generator:  8
生成器返回值: done

1
1
2
3
5
8

装饰器:

    首先有一个函数,它的参数也是函数。

def deco(func):
    for i in range(2):
        func()
def f():
    print('a')
deco(f)


a
a

    如果有很多函数都想被deco()调用(实现执行两次的效果),那就得每一次都使用deco调用该函数。所以就有了装饰器,在定义函数得时候就把deco得功能加进新声明的函数里了。

     装饰器的使用:

def a_new_decorator(a_func):
    # wrapTheFunction的作用在于进来一个函数,返回的仍然是一个函数
    def wrapTheFunction():
        print("I am doing some boring work before executing a_func()")
 
        a_func()
 
        print("I am doing some boring work after executing a_func()")
 
    return wrapTheFunction

@a_new_decorator 
def a_function_requiring_decoration():
    print("I am the function")

a_function_requiring_decoration()
#outputs: I am doing some boring work before executing a_func()
#         I am the function
#         I am doing some boring work after executing a_func()
print(a_function_requiring_decoration.__name__)
# Output: wrapTheFunction

Ouput输出应该是"a_function_requiring_decoration"。这里的函数被warpTheFunction替代了。它重写了我们函数的名字和注释文档(docstring)。幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps。我们修改上一个例子来使用functools.wraps:

from functools import wraps
 
def a_new_decorator(a_func):
    @wraps(a_func)
    def wrapTheFunction():
        print("I am doing some boring work before executing a_func()")
        a_func()
        print("I am doing some boring work after executing a_func()")
    return wrapTheFunction
 
@a_new_decorator
def a_function_requiring_decoration():
    """Hey yo! Decorate me!"""
    print("I am the function which needs some decoration to "
          "remove my foul smell")
 
print(a_function_requiring_decoration.__name__)
# Output: a_function_requiring_decoration

   带有参数的装饰器:

import time

# 带有固定参数
def deco(f):
    def wrapper(a,b):
        start_time = time.time()
        f(a,b)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
    return wrapper

@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))

if __name__ == '__main__':
    f(3,4)

# 无固定参数的装饰器
import time

def deco(f):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time_ = (end_time - start_time)*1000
        print("time is %d ms" %execution_time)
    return wrapper


@deco
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))

@deco
def f2(a,b,c):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b+c))


if __name__ == '__main__':
    f2(3,4,5)
    f(3,4)

     使用多个装饰器,装饰一个函数。

import time

def deco01(f):
    def wrapper(*args, **kwargs):
        print("this is deco01")
        start_time = time.time()
        f(*args, **kwargs)
        end_time = time.time()
        execution_time = (end_time - start_time)*1000
        print("time is %d ms" % execution_time)
        print("deco01 end here")
    return wrapper

def deco02(f):
    def wrapper(*args, **kwargs):
        print("this is deco02")
        f(*args, **kwargs)

        print("deco02 end here")
    return wrapper

@deco01
@deco02
def f(a,b):
    print("be on")
    time.sleep(1)
    print("result is %d" %(a+b))


if __name__ == '__main__':
    f(3,4)


# 对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。
# 在这个例子中,”f(3, 4) = deco01(deco02(f(3, 4)))”。
'''
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here
'''

  内置装饰器:

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。
staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
property 是属性的意思,表示可以通过通过类实例直接访问的信息

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值