首页 > 代码库 > icbc_auto_platform

icbc_auto_platform

 

1、包含yield的函数

假如你看到某个函数包含了yield,这意味着这个函数已经是一个Generator,它的执行会和其他普通的函数有很多不同。比如下面的简单的函数:

可以看到,调用h()之后,print 语句并没有执行!这就是yield,那么,如何让print 语句执行呢?这就是后面要讨论的问题,通过后面的讨论和学习,就会明白yield的工作原理了。

In [52]: def h():
   ....:         print ‘To be brave‘
   ....:         yield 5
   ....:   

In [53]: h()
Out[53]: <generator object h at 0x2a6f370>

In [54]: def h():
        print ‘To be brave‘

In [55]:

In [55]: h()
To be brave

2、yield是一个表达式

m = yield 5

表达式(yield 5)的返回值将赋值给m,所以,认为 m = 5 是错误的。那么如何获取(yield 5)的返回值呢?需要用到后面要介绍的send(msg)方法。

4、send(msg) 与 next()

其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做
c.next() 和 c.send(None) 作用是一样的。

In [78]: def h():
         print ‘Wen Chuan‘,
         m = yield 5  # Fighting!
         print‘m is %s:‘ % m
         d = yield 12
         print ‘We are together!‘
   ....:    

In [79]: c=h()

In [80]: c.next()
Wen ChuanOut[80]: 5

In [81]: c.next()
m is None:
Out[81]: 12

In [82]: c=h()

In [83]: c.next()     #相当于c.send(None)
Wen ChuanOut[83]: 5

In [84]: c.send(‘fighting‘)    #(yield 5)表达式被赋予了‘Fighting!‘
m is fighting:
Out[84]: 12

需要提醒的是,第一次调用时,请使用next()语句或是send(None),不能使用send发送一个非None的值,否则会出错的,因为没有yield语句来接收这个值。

5. send(msg) 与 next()的返回值

send(msg) 和 next()是有返回值的,它们的返回值很特殊,返回的是下一个yield表达式的参数。比如yield 5,则返回 5 。到这里,是不是明白了一些什么东西?本文第一个例子中,通过for i in alist 遍历 Generator,其实是每次都调用了alist.Next(),而每次alist.Next()的返回值正是yield的参数,即我们开始认为被压进去的东东。我们再延续上面的例子:

In [91]: def h():
         print ‘Wen Chuan‘,
         m = yield 5  # Fighting!
         print m
         d = yield 12
         print ‘We are together!‘
   ....:    

In [92]: c=h()

In [93]: m=c.next()   #m 获取了yield 5 的参数值 5
Wen Chuan

In [94]: d=c.send(‘fighting‘)   #d 获取了yield 12 的参数值12
fighting  --- 表达式(yield 12)的值m为fighting
In [96]: print ‘we will never forget the date‘,m,‘.‘,d
we will never forget the date 5 . 12

 

《提高你的Python: 解释‘yield’和‘Generators(生成器)’》

https://www.oschina.net/translate/improve-your-python-yield-and-generators-explained

yield就是专门给生成器用的return(加上点小魔法)。

下面是一个简单的生成器函数:

In [3]: def simple_generator_function():
   ...:     yield 1
   ...:     yield 2
   ...:     yield 3
   ...: 

这里有两个简单的方法来使用它:

In [4]: for value in simple_generator_function():
   ...:     print(value)
   ...:    
1
2
3

In [5]: our_generator = simple_generator_function()

In [6]: next(our_generator)
Out[6]: 1

In [7]: next(our_generator)
Out[7]: 2

In [8]: next(our_generator)
Out[8]: 3


 

In [1]: def is_prime(number):
   ...:     if number > 1:
   ...:         if number == 2:
   ...:             return True
   ...:         if number % 2 == 0:
   ...:             return False
   ...:         for current in range(3, int(math.sqrt(number) + 1), 2):
   ...:             if number % current == 0:
   ...:                 return False
   ...:         return True
   ...:     return False
   ...:

In [2]: def get_primes(number):
   ...:     while True:
   ...:         if is_prime(number):
   ...:             yield number
   ...:         number += 1
   ...:  

 

yield执行流程分析

调用get_primes

In [30]: def solve_number_10():
   ....:     # She *is* working on Project Euler #10, I knew it!
   ....:     total = 2
   ....:     for next_prime in get_primes(3):
   ....:         if next_prime < 2000000:
   ....:             total += next_prime
   ....:         else:
   ....:             print(total)
   ....:             return
   ....: 

我们来看一下solve_number_10的for循环中对get_primes的调用,观察一下前几个元素是如何创建的有助于我们的理解。当for循环从get_primes请求第一个值时,我们进入get_primes,这时与进入普通函数没有区别。

  1. 进入第三行的while循环
  2. 停在if条件判断(3是素数)
  3. 通过yield将3和执行控制权返回给solve_number_10

接下来,回到insolve_number_10:

  1. for循环得到返回值3
  2. for循环将其赋给next_prime
  3. total加上next_prime
  4. for循环从get_primes请求下一个值

这次,进入get_primes时并没有从开头执行,我们从第5行继续执行,也就是上次离开的地方。

In [2]: def get_primes(number):
   ...:     while True:
   ...:         if is_prime(number):
   ...:             yield number
   ...:         number += 1     # <<<<<<<<<<
   ...:  

最关键的是,number还保持我们上次调用yield时的值(例如3)。记住,yield会将值传给next()的调用方,同时还会保存生成器函数的“状态”。接下来,number加到4,回到while循环的开始处,然后继续增加直到得到下一个素数(5)。我们再一次把number的值通过yield返回给solve_number_10的for循环。这个周期会一直执行,直到for循环结束(得到的素数大于2,000,000)。

 

 

 


 

class AppApiHandler(BaseHandler):
    executor = ThreadPoolExecutor(max_workers=20)    ---- 最多20个线程

    @run_on_executor
    def run_app_api(self, app, func, args):
        role = self.get_current_user()
        args[‘APP_USER_ROLE‘] = role
        try:
            module = importlib.import_module(‘apps.%s.api‘ % app)   ---   装载模块‘icbc_auto_platform\apps\n5k_upgrade\api’
            app_func = getattr(module, func)   --- 返回api中的函数对象
            return app_func(**args)  ---  args返回api函数结果
        except ImportError:
            raise

icbc_auto_platform