函数进阶之结合tornado

一、本篇博文内容

1、协程函数
2、面向过程编程
3、递归和二分法

二、协程函数

协程函数:就是使用了yield表达式形式的生成器

首先函数的传参有几种?

三种:

1、实参形参传参

2、闭包的形式传参

3、就是通过yield的方式传参。好处:不用重复的神情局部内存空间

yield的表达式形式的应用

def eater(name):
    print("%s start to eat" %name)   #pyrene
    while True:
        food=yield
        print("%s eat %s"%(name,food))

a_g=eater("pyrene")
print(a_g)
print(next(a_g))  #因为这里执行yield的返回的结果,yield后面为空所以这里为none
print(next(a_g))  #这里执行了两步,所以结果为两个

分析:

首先这是一个生成器。

执行print(a_g)就会的到一个生成器<generator object eater at 0x00000160E546DFC0>

然后执行第一个print(next(a_g))  得到的结果为

pyrene start to eat

None

这是因为执行的时候next把name “pyrene”传递过来给了

 print("%s start to eat" %name) =pyrene start to eat 

之后继续往下执行,执行到yied的时候停止,并且把yied的返回值拿到,为空

然后执行第二个print(next(a_g)) 得到的结果为

pyrene eat None
None

因为这里执行food=yield,然后往下执行,由于这里是个死循环,所以又重新回到了yield。

yield的传参

先看下面代码:

def eater(name):
    print("%s start to eat" %name)
    food_list=[]
    while True:
        food=yield food_list
        food_list.append(food)
        print("%s eat %s"%(name,food))

a_g=eater("pyrene")  #拿到生成器
next(a_g)  #等同于alex_g.send(None)
print("=========")
# a_g.send("noodles")
print(a_g.send("noodles"))

执行结果:

pyrene start to eat
=========
pyrene eat noodles
[‘noodles‘]

如果满足yield传参需要有两个阶段:

第一阶段:必须初始化,保证生成器能够暂停初始化的位置

也就是

next(a_g)

第二阶段:给yield传值

print(a_g.send("noodles"))#send会把括号中的参数传递给yield,然后赋值给food

这里解释说明:

1、先给当前暂停位置的yield传值2、继续往下执行直到遇到下一个yield,然后返回yiled的结果

例子:

1、 下面是tornado的协程原理例子

from tornado import gen
    @gen.coroutine
    def fetch_coroutine(url):
        http_client = AsyncHTTPClient()
        response = yield http_client.fetch(url)
        return response.body

具体细节我会在后续的源码解析中一步一步的分析

2、实现一个单一请求的协程

def eater(name):
    print("%s start to eat" %name)
    food_list=[]
    while True:
        food=yield food_list
        food_list.append(food)
        print("%s eat %s"%(name,food))

def producer():
    a_g=eater("pyrene")
    next(a_g)
    while True:
        food=input(">>").strip()
        if not  food:continue
        print(a_g.send(food))
producer()

上面如何解决初始化的问题呢?

思路:

‘‘‘写一个装饰器解决初始化的问题1、首先写出装饰器的结构def init(func):    def wrapper(*args,**kwargs):        g=func(*args,**kwargs)        return g    return wrapper2、然后把功能加到装饰器中

‘‘‘如下:
def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper

@init
def eater(name):
    print("%s start to eat" %name)
    food_list=[]
    while True:
        food=yield food_list
        food_list.append(food)
        print("%s eat %s"%(name,food))
a_g=eater("pyrene")
print(a_g.send("noodles"))

3、多个请求的协程

import random
import time
from tornado import gen
from tornado.ioloop import IOLoop
@gen.coroutine
def get_url(url):
    wait_time = random.randint(1, 4)
    yield gen.sleep(wait_time)
    print(‘URL {} took {}s to get!‘.format(url, wait_time))
    raise gen.Return((url, wait_time))
@gen.coroutine
def process_once_everything_ready():
    before = time.time()
    coroutines = [get_url(url) for url in [‘URL1‘, ‘URL2‘, ‘URL3‘]]
    result = yield coroutines
    after = time.time()
    print(result)
    print(‘total time: {} seconds‘.format(after - before))
if __name__ == ‘__main__‘:
    print("First, process results as they come in:")
    IOLoop.current().run_sync(process_as_results_come_in)

面向过程编程

提到面向过程编程,可能都会想到函数,。如果是这样的话,那么就不怎么全面了

面向过程:核心就是过程两个字,过程即解决问题的步骤

看下面例子:

要求实现grep -rl "error" /dir 这样的小程序

代码实现如下:

目录结构如下:

然后在

a1.txt a2.txt b1.txt文件中有包含若干个error
#第一阶段:找到所有文件的绝对路径   拿到文件和文件的父 级目录就是绝对路径
import os
def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs)
        next(g)
        return g
    return wrapper
@init
def search(target):
    while True:
        filepath=yield
        g=os.walk(filepath)
        for pardir,_,files in g:
            for file in files:
                abspath=r"%s\%s"%(pardir,file)
                target.send(abspath)
# g=search()
# g.send(r"F:\18期代码\day5\a")
#第二阶段:打开文件
@init
def opener(target):
    while True:
        abspath=yield
        with open(abspath,"rb") as f:
            target.send((abspath,f))

# g = search(opener())
# g.send(r"F:\18期代码\day5\a")
#第三阶段:循环读出每一行的内容
@init
def cat(target):
    while True:
        abspath,f=yield    #这里应该把文件和路径都传输过来  (abspath,f)
        for line in f:
            res=target.send((abspath,line))
            if res:break
# g = search(opener(cat()))
# g.send(r"F:\18期代码\day5\a")
#第四阶段:过滤
@init
def grep(pattern,target):
    tag=False     #通过上面返回值去重操作
    while True:
        abspath,line=yield tag
        tag=False
        if pattern in line:
            target.send(abspath)
            tag=True
# g = search(opener(cat(grep("error"))))
# g.send(r"F:\18期代码\day5\a")
#打印该行属于的文件名
@init
def printer():
    while True:
        abspath=yield
        print(abspath)
g = search(opener(cat(grep("error".encode("utf-8"),printer()))))
g.send(r"C:\Users\Administrator\PycharmProjects\T4\app.py")

解析:

首先分析参数:

-r  递归的去找所有的目录-l  列出文件名,这里是列出包含error的文件名上面是查找目录中所有的文件中包含error的文件

然后就是os模块中的walk的使用:

g=os.walk(文件路径)   --》生成器next(g)=([父目录],[子目录文件夹],[文件])  返回一个元祖,里面有三个元素

面向过程编程的优点:程序结构清晰,可以把复杂的问题简单化,流程化

缺点:科扩展性差

应用场景:linux kernel  git   httpd  shell脚本   还有一个很多人都不熟悉的编程序言haskell就是大名鼎鼎的面向对象编程思想

递归和二分法

递归调用:

在调用一个函数的过程中,直接或者间接的调用了函数本身。

注意,python中的递归性能低的原因是调用一次函数本身就会保存这次的状态,一直等到结束才释放

递归的两个阶段:递推、回溯

简单的例子:

def age(n):
    if n==1:
        return 18
    return age(n-1)+2g=age(3)print(g)

例子2:如何把下面这个列表中的所有元素取出来?

l =[1, 2, [3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15,[16,[17,]],19]]]]]]]
def search(l):
    for item in l:
        if type(item) is list:
            search(item)
        else:
            print(item)

search(l)

二分法

当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。主要思想是:(设查找的数组区间为array[low, high])

二分法:就可以用递归的思想来解决

如:

l=[1,2,3,5,7,12,44,77]
def binary_search(l,num):
    print(l)
    if len(l)>1:
        mid_index=len(l)//2
        if num>l[mid_index]:
            l=l[mid_index+1:]
            binary_search(l,num)
        elif num<l[mid_index]:
            l=l[:mid_index]
            binary_search(l, num)
        else:
            print("find it")
    else:
        if l[0]==num:
            print("find it")
        else:
            print("error")
        return
binary_search(l,3)
时间: 2025-01-13 17:53:28

函数进阶之结合tornado的相关文章

Android.mk (2) 函数进阶教程 - 分支、循环、子程序

https://www.jianshu.com/p/674dc7d7b4b0 函数进阶教程 - 分支.循环.子程序 按照面向过程程序设计的标准流程,我们讲完了顺序结构,就要讲分支.循环和子程序.下面我们就开始讲用于分支.循环和子程序调用功能的函数. 分支函数 要走分支,一定是要有条件要判断. 在Makefile里,最主要的判断就是看字符串能不能找到了. 通过findstring函数来进行这个判断,然后用if函数使用findstring函数的结果. 例: .PHONY : all5 bootoat

Python 全栈开发:python函数进阶

python函数进阶 函数嵌套 函数对象 命名空间与作用域 闭包函数 装饰器 一.函数嵌套 函数的嵌套定义 def func1(): print('from func1') def func2(): #func2=内存地址 print('from func2') print(func2) func1() 函数的嵌套调用 # 比较两个数的大小 def max2(x,y): if x > y: return x else: return y # 比较三个数的大小 def max3(x,y,z): r

python大法好——递归、内置函数、函数进阶

1.递归(自己干自己) def fun(n): n=n/2 print(n) if(n>2) fun(n) #函数调用 fun(10) 结果是5 2 1 0 递归的执行过程:递归执行到最里面一层,外面的层还没有结束,所以由内而外结束. 证明: def fun(n): n=n/2 print(n) if(n>2) fun(n) print(n) #函数调用 fun(10) 结果是 0 1 2 5 递归获取最后一个值: def calc(n,count): print(n,count) if co

生成器函数进阶

1.生成器函数进阶(一) 1 # 生成器函数进阶 2 3 def generator(): 4 print(123) 5 num = yield 1 # 当第一个__next__发生时,yiled 1先被执行,被返回,停在了这里,之后当send来了后,send的参数先赋值给了yield的左值,之后再执行下一个yield之前的代码 6 # send()获取yield值之前,会给上一个yield的位置传递一个参数数据,这个数据可以被上一个yield的左值接收 7 # 使用生成器的send()方法,就

函数—函数进阶(二)

函数-函数进阶(二) 函数-函数进阶-列表生成式 1 #列表回顾 2 name = [2,5,7,9,4] 3 print(name) 4 for i in name: 5 print(i) 6 #结果为: 7 # [2, 5, 7, 9, 4] 8 # 2 9 # 5 10 # 7 11 # 9 12 # 4 13 14 #枚举 15 for index,i in enumerate(name): 16 print(index,i) 17 #结果为: 18 # 0 2 19 # 1 5 20

No-12.函数进阶

函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形式 无参数,无返回值 无参数,有返回值 有参数,无返回值 有参数,有返回值 定义函数时,是否接收参数,或者是否返回结果,是根据 实际的功能需求 来决定的! 如果函数 内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部 如果希望一个函数 执行完成后,向外界汇报执行结果,就可以增加函数的返回值

~~函数进阶(一):装饰器~~

进击のpython 函数进阶-装饰器 知道京东吧(不知道?那你知道淘宝,蘑菇街吧) 我们身为用户,在进入界面的时候 首先会提示我们登陆是吧 当我们登陆的时候,接下来的所有操作就不用再验证身份了 否则,一到收藏啊,关注啊,就需要我们重新登陆 那我们可不可以做一个这个呢?? 没有数据库,我们模拟一个数据库,懂我意思吧! DB = { "login": False, "user_name": "poddy", "password":

python基础_函数进阶

函数进阶 目标 函数参数和返回值的作用 函数的返回值 进阶 函数的参数 进阶 递归函数 01. 函数参数和返回值的作用 函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形式 无参数,无返回值 无参数,有返回值 有参数,无返回值 有参数,有返回值 定义函数时,是否接收参数,或者是否返回结果,是根据 实际的功能需求 来决定的! 如果函数 内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部 如果希望一个函数 执行完成后,向外界汇报执行结果,就可以增加函数的返回值

第五篇 函数进阶

目录 第五篇 函数进阶 一 闭包函数 二 装饰器 三 迭代器 四 三元表达式 五 列表推导式 六 字典生成式 七 生成器 八 递归 九 匿名函数 十 内置函数 第五篇 函数进阶 ==回顾基础== 函数对象:可以将定义在函数内的函数返回到全局使用,从而打破函数的层级限制. 名称空间与作用域:作用域关系在函数定义阶段时就已经固定死了,与调用位置无关,即在任意位置调用函数都需要跑到定义函数时找到作用域关系. 一 闭包函数 闭包 闭就是封闭(函数内部函数),包就是包含(该内部函数对外部作用域而非全局作用