python进阶

1.迭代器
1.1 定义
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
1.2 可迭代对象 Iterable
以直接作用于for 循环的数据类型有一下几种:
一类:集合数据类型:list,tuple,dict,set,str
一类generator ,包含生成器和带yieldgenerator function
这些可以直接用于for循环的对象统称为可迭代对象:Iterable

1.3 iter()函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:

from collections import Iterable
a=[1,2,3,4,5,6]
a=iter(a)
print(next(a))

2. 生成器
生成器与列表生成式的本质区别就是:一个已经生成数据了,使用时,如果数据过大,会产生内存溢出,而生成器是只有循环时,才会生成数据。
2.1 generator创建方法
1.把一个列表生成式的[]改成(),就创建了一个generator

 g = (x * x for x in range(10))

2.2 使用了yield的函数就是生成器
yield关键字可以看作特殊的return

def fib(times): #打印斐波拉契数列钱times位。
    n=0
    a,b=0,1
    while n

发现如果生成器是函数的话,使用for遍历,无法获取函数的返回值。

方法2:使用next()函数来遍历迭代,可以获取生成器函数的返回值。

f=fib(10)
while True:
    try:  #因为不停的调用next会报异常,所以要捕捉处理异常
        x=next(f)   #这里不能直接写next(fib(10)),f否则每次重复调用1
        print(x)
    except StopIteration as e:
        print('生成器返回值:%s'%e.value)
        break

3.装饰器

装饰器(Decorators)修改其他函数的功能的函数,有助于让我们的代码更简短。在不改动原代码的情况下,在定义一个函数。

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)

这里的deco函数就是装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数f()就在返回函数wrapper的内部执行。然后在函数f()前面加上@deco,f()函数就相当于被注入了计时功能,现在只要调用f(),它就已经变身为“新的功能更多的函数”

3.2 无固定参数的装饰器

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)

python 中 *args 和kwargs的区别**
1. * args的使用方法:*args将参数打包成tuple给函数调用

def func(x,y,*args):
    print(x,y,args)
func(1,2,3,4,5)
  1. **kwargs:打包关键字参数成dict给函数调用
def function(**kwargs):
    print(kwargs)

function(a=1, b=2, c=3)

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

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)

4. Filtermapreduce 方法

map()函数:它接收一个f 和一个list,并通过把函数f一次作用在list的每个元素上,得到一个新的list并返回。
reduce 函数即化简函数;每一次迭代都将上一次的迭代结果与下一个元素一同传入二元func函数中去执行。

 reduce(func,seq[,int()])

filter:功能是过滤掉序列中不符合函数条件的元素。

l=[x for x in range(0,10)]
l=list(filter(lambda x : x%2==0,l))
print(l)

5. 函数式编程

变量可以指向函数

f=abs     #abs为绝对值函数
print(f(-10))

传入函数:
既然变量可以指向函数,函数的参数能接受变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

def add(a,b,f):
    return f(a)+f(b)

4.2 函数作为返回值
高阶函数除了可以作为接收函数作为参数外,还可以吧结果值返回。
可变参求和函数

def cal_sum(*args):
    ax=0
    for i in args:
        ax+=i
    return ax

但如果不需要立即求和,而是在后面的代码中,根据需要在计算,可以不返回求和的结果,而是返回求和的函数。

def lazy_sum(*args):
    def sum():
        ax=0
        for i in args:
            ax+=i
        return ax  #return必须要有,才能返回到外部函数
    return sum
f=lazy_sum(1,3,5,7,9)
f()   #调用f时,才真正计算求和的结果

在上面例子中,在函数lazy_sum中又定义了函数sum,并且内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为"闭包closure"的程序结构拥有极大的威力。
注意:每次调用lazy_sum时,都会返回一个新的函数

闭包
需要注意的问题是,返回的函数并没有立刻执行,而是知道调用了f()才执行

def count():
    fs=[]
    for i in range(1,4):
        def f():
            return i*i
        fs.append(f)
    return fs
f1,f2,f3=count()
f1()

结果全是9,原因在于返回的函数引用了变量i,但它并没有立刻执行,等到3个函数都返回时,他们所应用的变量i已经变成了3,因此最终结果为9.

因此,返回闭包时牢记:返回函数不要引用任何循环变量,或者后续发生变化的变量
如果一定要引用循环变量,则在创建一个函数,用该函数的参数绑定循环变量当前值,无论循环变量后续如何更改,已经绑定到函数参数的值不变。

def count():
    def f(j):                   #可利用lambda函数简化
        def g():
            return j*j
        return g
    fs=[]
    for i in range(1,4):
        fs.append(f(i))#f(i)立即被执行,因此i的当前值被传入f()
    return fs
f1,f2,f3=count()     #返回1,4,9

你可能感兴趣的:(python)