欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python 函数进阶2

程序员文章站 2024-03-17 16:25:58
...

一、协程函数与yield

协程,又称微线程,纤程。英文名Coroutine。

用法:

def eater(name):
    print('%s 说:我买了好多东西:' %name)
    food_list=[]
    while True:
        food=yield food_list
        food_list.append(food) #['香蕉','苹果']
        print('%s 最爱吃的 %s' %(name,food))
name_g=eater('翔子')

 

#第一阶段:初始化
next(name_g) #等同于name_g.send(None)
#第二阶段:给yield传值
print(name_g.send('香蕉')) #1 先给当前暂停位置的yield传骨头 2 继续往下执行,直到再次碰到yield,然后暂停并且把yield后的返回值当做本次调用的返回值
print(name_g.send('苹果'))
print(name_g.send('梨'))

1、把函数的执行结果封装好__iter__和__next__,即得到一个迭代器
2、与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yield可以返回多次值;
3、函数暂停与再继续运行的状态是有yield保存

解决初始化问题,使用装饰器

def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper
@init
def eater(name):
    print('%s 说:我买了好多东西:' %name)
    food_list=[]
    while True:
        food=yield food_list
        food_list.append(food) #['骨头','菜汤']
        print('%s 最爱吃的 %s' %(name,food))
name_g=eater('翔子')
#第二阶段:给yield传值
print(name_g.send('香蕉'))

1、先给当前暂停位置的yield传香蕉;
2、继续往下执行,直到再次碰到yield,然后暂停并且把yield后的返回值当做本次调用的返回值;

二、递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

#直接调用
def func():
    print('from func')
    func()
func()

#间接调用
def foo():
    print('from foo')
    bar()
def bar():
    print('from bar')
    foo()
foo()

举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出:

fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n

所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。

于是,fact(n)用递归的方式写出来就是:

def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)

上面就是一个递归函数。可以试试:

>>> fact(1)
1
>>> fact(5)
120

如果我们计算fact(5),可以根据函数定义看到计算过程如下:

===> fact(5)

===> 5 * fact(4)

===> 5 * (4 * fact(3))

===> 5 * (4 * (3 * fact(2)))

===> 5 * (4 * (3 * (2 * fact(1))))

===> 5 * (4 * (3 * (2 * 1)))

===> 5 * (4 * (3 * 2))

===> 5 * (4 * 6)

===> 5 * 24

===> 120

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

总结:

1、使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。

2、针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。

3、Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

三、二分法

二分法是一种快速查找的方法,时间复杂度低,逻辑简单易懂,总的来说就是不断的除以2除以2...

例:

l = [1,2,5,7,10,31,44,47,56,99,102,130,240]  查找32 是否在其中

1.如果找到该值就返回

2.如果找不到该值就返回该值的上一个Index和下一个Index

3.小于List[0] 返回0

4.大于len(List)返回该List[-1]

def binary_search(l,num):
    print(l) #[10, 31]
    if len(l) > 1:
        mid_index=len(l)//2 #1
        if num > l[mid_index]:
            #in the right
            l=l[mid_index:] #l=[31]
            binary_search(l,num)
        elif num < l[mid_index]:
            #in the left
            l=l[:mid_index]
            binary_search(l,num)
        else:
            print('find it')
    else:
        if l[0] == num:
            print('find it')
        else:
            print('not exist')
        return
    binary_search(l,32)

执行结果:

[1, 2, 5, 7, 10, 31, 44, 47, 56, 99, 102, 130, 240]
[1, 2, 5, 7, 10, 31]
[7, 10, 31]
[10, 31]
[31]
not exist

上一篇: Python函数进阶

下一篇: