python协程2:yield from 从入门到精通

上一篇python协程1:yield的使用介绍了: 生成器作为协程使用时的行为和状态 使用装饰器预激协程 调用方如何使用生成器对象的 .throw(…) 和 .close() 方法控制协程 这一篇将介绍: 协程终止时如何返回值 yield新句法的用途和语义 HUGOMORE42 让协程返回值 先看一个例子: 这段代码会返回最终均值的结果,每次激活协程时不会产出移动平均值,而是最后一次返回。 #! -*- coding: utf-8 -*- from collections import namedtuple Result = namedtuple('Result', 'count average') def averager(): total = 0.0 count = 0 average = None while True: term = yield if term is None: break # 为了返回值,协程必须正常终止;这里是退出条件 total += term count += 1 average = total/count # 返回一个namedtuple,包含count和average两个字段。在python3.3前,如果生成器返回值,会报错 return Result(count, average) 我们调用这段代码,结果如下 >>> coro_avg = averager() >>> next(coro_avg) >>> coro_avg.send(20) # 并没有返回值 >>> coro_avg.send(30) >>> coro_avg.send(40) >>> coro_avg.send(None) # 发送None终止循环,导致协程结束。生成器对象会抛出StopIteration异常。异常对象的value属性保存着返回值。 Traceback (most recent call last): ... StopIteration: Result(count=3, average=30) return 表达式的值会传给调用方,赋值给StopIteration 异常的一个属性。这样做虽然看着别扭,但为了保留生成器对象耗尽时抛出StopIteration异常的行为,也可以理解。 ...

2017-06-14 · 5 min · 858 words

python协程1:协程 10分钟入门

最近找到一本python好书《流畅的python》,是到现在为止看到的对python高级特性讲述最详细的一本。 看了协程一章,做个读书笔记,加深印象。 协程定义 协程的底层架构是在pep342 中定义,并在python2.5 实现的。 HUGOMORE42 python2.5 中,yield关键字可以在表达式中使用,而且生成器API中增加了 .send(value)方法。生成器可以使用.send(…)方法发送数据,发送的数据会成为生成器函数中yield表达式的值。 协程是指一个过程,这个过程与调用方协作,产出有调用方提供的值。因此,生成器可以作为协程使用。 除了 .send(…)方法,pep342 和添加了 .throw(…)(让调用方抛出异常,在生成器中处理)和.close()(终止生成器)方法。 python3.3后,pep380对生成器函数做了两处改动: 生成器可以返回一个值;以前,如果生成器中给return语句提供值,会抛出SyntaxError异常。 引入yield from 语法,使用它可以把复杂的生成器重构成小型的嵌套生成器,省去之前把生成器的工作委托给子生成器所需的大量模板代码。 协程生成器的基本行为 首先说明一下,协程有四个状态,可以使用inspect.getgeneratorstate(…)函数确定: GEN_CREATED # 等待开始执行 GEN_RUNNING # 解释器正在执行(只有在多线程应用中才能看到这个状态) GEN_SUSPENDED # 在yield表达式处暂停 GEN_CLOSED # 执行结束 #! -*- coding: utf-8 -*- import inspect # 协程使用生成器函数定义:定义体中有yield关键字。 def simple_coroutine(): print('-> coroutine started') # yield 在表达式中使用;如果协程只需要从客户那里接收数据,yield关键字右边不需要加表达式(yield默认返回None) x = yield print('-> coroutine received:', x) my_coro = simple_coroutine() my_coro # 和创建生成器的方式一样,调用函数得到生成器对象。 # 协程处于 GEN_CREATED (等待开始状态) print(inspect.getgeneratorstate(my_coro)) my_coro.send(None) # 首先要调用next()函数,因为生成器还没有启动,没有在yield语句处暂停,所以开始无法发送数据 # 发送 None 可以达到相同的效果 my_coro.send(None) next(my_coro) # 此时协程处于 GEN_SUSPENDED (在yield表达式处暂停) print(inspect.getgeneratorstate(my_coro)) # 调用这个方法后,协程定义体中的yield表达式会计算出42;现在协程会恢复,一直运行到下一个yield表达式,或者终止。 my_coro.send(42) print(inspect.getgeneratorstate(my_coro)) 运行上述代码,输出结果如下 ...

2017-06-12 · 4 min · 644 words

CSS入门指南-1:工作原理

这是CSS设计指南的读书笔记,用于加深学习效果。 最近想做一个小程序,前端是必修课,那就从css开始吧。 css 工作原理 每个html元素都有一组样式属性,可以通过css来设定。当html元素的同一个样式属性有多种样式值的时候,css就要靠层叠机智来决定最终应用哪种样式。 HUGOMORE42 css规则 规则实际上是一条完整的css指令,规则声明了要修改的元素和要应用给改元素的样式。 为文档添加样式的三种方法: 写在元素标签里(也叫行内样式,只能影响它所在的标签,会覆盖嵌入样式和链接样式) 写在<style> 标签里(也就嵌入样式,应用范围仅限于当前页面,页面样式会覆盖外部样式表中的样式,但会被行内样式覆盖) 写在单独css样式表中(也叫链接样式,样式表是一个扩展名为.css 的文件,可以在任意多个HTML页面链接同一个样式表文件。链接样式的作用范围是整个网站) 除了这三种为页面添加样式的方法,还有一种在样式表中链接其他样式表的方法,使用@import 指令:例如 @import url(css/styles.css) @import 指令必须出现在样式表中其他样式之前,否则@吹灭;@import引用的样式表不会被加载。 对这个基本的结构有三种方法可以进行扩展 **第一种方法:**多个声明包含在一条规则里。 p {color: red; font-size: 12px; font-weight: bold;} **第二种方法:**多个选择器组合在一起。例如:如果想让<h1>、<h2>和<h3>的文本都变成蓝色粗体可以这么写: h1 {color: blue; font-weight: bold;} h2 {color: blue; font-weight: bold;} h3 {color: blue; font-weight: bold;} 也可以这么写: h1, h2, h3 {color: blue; font-weight: bold;} 分组选择符以逗号作为分隔符 第三种方法: 多条规则应用给一个选择符。 例如,写完上边的规则,还想把h3变成斜体,那么可以再为h3单独写一条规则: h1, h2, h3 {color: blue; font-weight: bold;} h3 {font-style: italic;} 选择特定元素的选择符 用于选择特定元素的操作符有三种 上下文选择符。基于祖先或者同胞元素选择一个元素。 ID和类选择符。基于id和class属性的值选择元素。 属性选择符。基于属性的有无和特征选择元素。 上下文选择符 比如我们想给article中的段落设置不同的字号,可以使用上下文选择符来解决。 上下文选择符的格式如下: 标签1 标签2 {声明} 其中标签2 是我们要选择的目标,而且只有在 标签1是其祖先元素的情况下才会被选中。 上下文选择符,叫后代组合式选择符,就是一组以空格分隔的标签名。用于选择作为特定祖先元素后代的标签。 article p {font-weight: bold;} 上边例子中,只有article后代的p元素才会应用后边的样式。 上下文选择符以空格作为分隔符 特殊的上下文选择符 子选择符 > 格式如下: 标签1 > 标签2 标签1 必须是 标签2 的父元素,不能是其它的祖先元素。 ...

2017-05-27 · 3 min · 451 words

跟着代码学go 002 -- 控制流

控制流 上一篇我们了解了golang 的变量、函数和基本类型,这一篇将介绍一下控制流 现在我们看一个复杂点的例子: HUGOMORE42 fibonacci(递归版) 01 package main 02 03 import "fmt" 04 05 func main() { 06 result := 0 07 for i := 0; i <= 10; i++ { 08 result = fibonacci(i) 09 fmt.Printf("fibonacci(%d) is: %d\n", i, result) 10 } 11 } 12 13 func fibonacci(n int) (res int) { 14 if n <= 1 { 15 res = 1 16 } else { 17 res = fibonacci(n-1) + fibonacci(n-2) 18 } 19 return 20 } // outputs fibonacci(0) is: 1 fibonacci(1) is: 1 fibonacci(2) is: 2 fibonacci(3) is: 3 fibonacci(4) is: 5 fibonacci(5) is: 8 fibonacci(6) is: 13 fibonacci(7) is: 21 fibonacci(8) is: 34 fibonacci(9) is: 55 fibonacci(10) is: 89 for i := 0; i <= 10; i++ {} 第7行是一个循环结构 这里for 循环是一个控制流 控制流 For Go 只有一种循环接口– for 循环 ...

2016-04-26 · 4 min · 836 words

跟着代码学go 001 -- 变量&函数

变量&函数 最近在学习golang,写下学习笔记提升记忆。 为了看起来不是那么枯燥,本学习笔记采用分析代码的形式。 首先搬出我们最经典的第一段代码: HUGOMORE42 hello world package main // 0 import "fmt" // 1实现格式化的 I/O /* Print something */ // 2 func main() { // 3 fmt.Println("Hello, world; or καλημε ́ρα κóσμε; orこんにちは 世界") // 4 } 首先我们要认识到 每个Go 程序都是由包组成,程序的运行入口是包main 首行这个是必须的。所有的 Go 文件以 package 开头,对于独立运行的执行文件必须是 package main; 这是说需要将fmt加入到main。不是main 的包被称为库 末尾以 // 开头的内容是单行注释 Package fmt包含有格式化I/O函数,类似于C语言的printf和scanf 这也是注释,表示多行注释。 package main 必须首先出现,紧跟着是 import。在 Go 中,package 总是首先出现, 然后是 import,然后是其他所有内容。当 Go 程序在执行的时候,首先调用的函数 是 main.main(),这是从 C 中继承而来。这里定义了这个函数 调用了来自于 fmt 包的函数打印字符串到屏幕。字符串由 " 包裹,并且可以包含非 ASCII 的字符。这里使用了希腊文和日文、中文" 编译和运行代码 构建 Go 程序的最佳途径是使用 go 工具。 构建 helloworld 只需要: ...

2016-04-25 · 5 min · 922 words

golang 介绍

1. Golang 是什么 Go 官方说明: Go 编程语言是一个使得程序员更加有效率的开源项目。Go 是有表达力、简 洁、清晰和有效率的。它的并行机制使其很容易编写多核和网络应用,而新的类型系统允许构建有 性的模块化程序。Go 编译到机器码非常快 速,同时具有便利的垃圾回收和强大的运行时反射。它是快速的、静态类 型编译语言,但是感觉上是动态类型的,解释型语言 HUGOMORE42 2. 为什么要开发这个语言 Go 语言的发展目标 Go 语言的主要目标是将静态语言的安全性和高效性与动态语言的易开发性进行有机结合 Go 语言是一门类型安全和内存安全的编程语言。虽然 Go 语言中仍有指针的存在,但并不允许进行指针运算。 Go 语言的另一个目标是对于网络通信、并发和并行编程的极佳支持,从而更好地利用大量的分布式和多核的计算机 Go 语言中另一个非常重要的特性就是它的构建速度(编译和链接到机器代码的速度),一般情况下构建一个程序的时间只需要数百毫秒到几秒。 Go 语言实现高效快速的垃圾回收(使用了一个简单的标记-清除算法)。 3. 有什么特性&&用途 语言的特性 清晰并且简洁 Go 努力保持小并且优美,你可以在短短几行代码里做许多事情; 并行 Go 语言从本质上(程序和结构方面)来实现并发编程。 Go 让函数很容易成为非常轻量的线程。这些线程在 Go 中被叫做 goroutines Channel 这些 goroutines 之间的通讯由 channel[18, 25] 完成 快速 编译很快,执行也很快。目标是跟 C 一样快。编译时间用秒计算; Go 的可执行文件都比相对应的源代码文件要大很多,这恰恰说明了 Go 的 runtime 嵌入到了每一个可执行文件当中。当然,在部署到数量巨大的集群时,较大的文件体积也是比较头疼的问题。但总得来说,Go 的部署工作还是要比 Java 和 Python 轻松得多。因为 Go 不需要依赖任何其它文件,它只需要一个单独的静态文件,这样你也不会像使用其它语言一样在各种不同版本的依赖文件之间混淆。 安全 当转换一个类型到另一个类型的时候需要显式的转换并遵循严格的规则。Go 有 垃圾收集(使用了一个简单的标记-清除算法),在 Go 中无须 free(),语言会处理这一切; 值得注意的是,因为垃圾回收和自动内存分配的原因,Go 语言不适合用来开发对实时性要求很高的软件。 ...

2016-04-14 · 2 min · 271 words