Python语言编程之学习问题集合

1.为什么C语言较Python等脚本语言编写计算密集型任务效率更高,而Python等脚本语言编写IO密集型任务较C语言效率更高?

    答:可能的解释a:IO密集型任务比如WEB服务,这类服务的开发代码可能会经常性的更改、更新,所以需要开发效率较高的代码,即代码量少,码起来较快。

2.在进行TCP编程,调用socket进行通信时,客户端发送数据出去,一定会等到服务器传送数据回,才会接着执行后面的代码吗?

    答:这是同步IO模型。异步IO模型便能有效解决这个问题,使得主线程在等待一个IO操作返回结果的过程中,能继续执行下面的代码。

3.在异步IO模型下,一个线程就可以同时处理多个IO请求,并且没有切换线程的操作。对于大多数IO密集型的应用程序,使用异步IO将大大提升系统的多任务处理能力。为什么一个线程处理多个IO请求时并没有切换线程的操作,那它又是如何进行多个IO请求的处理呢?

    答:利用协程,使用yield关键字将协程标记为generator,在执行多协程(共享一个线程)时,便能利用yield的中断及返回值实现协程之间的切换操作,从而实现异步IO。

4.yield表达式如何理解其执行机制?

    答:运行如下代码: 

def consumer():
    r = ''
    while True:
        print(r)
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

c = consumer()
produce(c)

结果为:

                  #空行
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
200 OK
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
200 OK
[PRODUCER] Consumer return: 200 OK

分析可发现:凡send(mesg)方法即执行相应generator函数并把mesg赋给当前yield表示式,然后直至遇到下一个yield关键字(如后面无yield,则需.close(),否则会抛出StopIteration异常),并返回下一个yield的参数(此例中为r)。

    c.send(None)初始化即从函数开始执行,传入None是因为最开始没有yield表达式接收赋值,然后直到遇到yield(1号),并返回yield的参数r(为' '),亦跳出consumer函数,回到produce函数中继续执行下面的代码;

    遇到c.send(n)又开始切换到consumer中执行,从上次中断处执行即yield处,将n赋值给本次yield(1号)表达式,然后继续执行consumer中下面的代码,直至遇到下一次yield(2号),返回yield(2号)的参数r,中断consumer,切换produce函数,接着send(n)继续执行;如此循环,直至produce结束。

总结:有yield表达式的执行方式即是利用c.send(mesg)切换到c函数中执行,

遇到yield表达式,将mesg赋值给yield表达式,继续执行c函数,

并在下一次yield中断c函数的执行,并将此时yield的参数r作为c.send(mesg)的返回值,回到c.send(mesg)所在的代码处执行下面的代码,

再下一次c.send(mesg)从中断的yield处执行c函数。

猜你喜欢

转载自blog.csdn.net/hhu_luqi/article/details/84873715