这三个方法,在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调用但是由于没有其他过程,在被调用时只会返回值,不会有其他动作。