修饰符@,装饰器(decorator),迭代器(iterator),生成器(Generator)的一些见解

       这三个方法,在Python里的使用并不多,然而,各大互联网公司还特别喜欢考这一方面的。以前因为不常用,有些忽视了这几个方法,碰了几次壁后,决心好好整理一番这三个方法(以下代码均在python3.6的环境下实验):

      1.修饰符@和装饰器

      很多地方说的修饰符,装饰器其实是同一个东西

      '@' 用做函数的修饰符。

      修饰符出现在函数的前一行。 

      一个修饰符就是一个函数,它将被修饰的函数作为参数,并返回修饰后的同名函数,借用一个例子如下。

def square_sum(fn):
    def square(*args):
        print ("1---", args)
        n = args[0]
        # return n*(n-1)*(2*n-1)/6
        print ("2==", n*(n-1)*(2*n-1)/6)
        print (fn.__name__)
        fn(n*(n-1)*(2*n-1)/6)
        print ("*"*15)
        return fn(n*(n-1)*(2*n-1)/6)
    return square
@square_sum
def sum_a(a):
    print ("3=", a)    
sum_a(10)
结果如下:
1--- (10,)
2== 285.0
sum_a
3= 285.0
***************
3= 285.0

可以看到,在sum_a(10)的时候,参数并不是传给了函数sum_a,而是给了修饰符@square_sum,而参数fn代表的"__name__"也成了要与修饰的函数重名。而square_sum(fn)的返回结果,才是sum_a()真正的输入参数。

2.装饰器(decorator)里的静态方法和类方法

    @staticmethod是静态方法,在使用的时候可以不需要self参数,直接调用

class Foo:
    @staticmethod #装饰器,静态方法
    def spam(x,y,z):
        print(x,y,z)
print(type(Foo.spam)) #类型就是class function
Foo.spam(1,2,3) #传参
f1=Foo()
f1.spam(3,3,3) #传参
<class 'function'>
1 2 3
3 3 3

这里第一次传参的时候,可以看到,并没有给类class Foo进行实例化对象,就直接调用了里面的方法。第二次传参的时候,才进行类的实例化对象。

classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

class A(object):
    bar = 1
    def func1(self):  
        print ('foo') 
    @classmethod         #类方法
    def func2(cls):
        print ('func2')
        print (cls.bar)
        cls().func1()   # classmethod可以直接调用类里的 foo 方法 
A.func2()               # 不需要实例化,
func2
1
foo

类方法定义后,可以获取类里的属性,对象,成员等。

3.iter迭代器 

it = iter([1,2,3])
print(next(it))
print(next(it))
#print(next(it))
#print(next(it))
for i in it:
    print(i)
1
2
3

        会发现以上代码使用next()注释掉几行,仍然结果是1,2,3,并没有变化,next()方法返回下一个值,然而调用了一次next后,相应的it迭代器里面的值也减少了。for循环里的值也相应的减少了。最后在用next()的时候,如果没有返回值,会引发一个StopIteration的异常。

最后说一下,iter的实用价值在于:如果列表过大,如果有100万个词甚至更大,组成的列表,一次加载整个列表,会导致内存不足,在使用的时候,就要考虑使用迭代器,降低列表对内存的占用。

4.yield生成器

         任何包含yield语句的函数都被称为生成器。         

def power(values):
    for value in values:
        print ("powing %s" % value)
        yield value
def add(values):
    for value in values:
        if value % 2 == 0:
            yield value + 3
        else:
            yield value + 2
elements = [1, 4, 7]
add(power(elements))
for i in add(power(elements)):
        print(i)
powing 1
3
powing 4
7
powing 7
9

 生成器是以函数的方式被创建,在使用的时候只有在被next()调用或者for循环调用时,里面的过程才会被执行,如同上面的例子只是单纯调用add这个对象时,add里面的过程没有被执行哦

迭代器同样可以被for和next调用但是由于没有其他过程,在被调用时只会返回值,不会有其他动作。

猜你喜欢

转载自blog.csdn.net/u010883226/article/details/84340713