|
Size: 3839
Comment:
|
Size: 8132
Comment:
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 6: | Line 6: |
| :status: 草稿 ;HuangYi; 10%; | :status: 草稿 ;HuangYi; 40%; |
| Line 18: | Line 18: |
| ``if`` 语句后面跟 ``else`` 自不必说,连 ``for`` 、 ``while`` 语句也可以跟 ``else`` 子句! TODO: 关于不同语句中的 ``else`` |
``if`` 语句后面跟 ``else`` 自不必说,连 ``for`` 、 ``while`` 语句也可以跟 ``else`` 子句! ``else`` 子句的含义根据所处语句的不同自然也会有所不同。 |
| Line 24: | Line 24: |
| 最基本的用法: | |
| Line 43: | Line 44: |
| ``elif`` 就是 else if 的缩写。 python 没有 switch 语句,因为觉得没必要,原因之一是 if elif else 已经足以应付大部分情况。 况且对于很大一部分其他的 switch 应用场景,python 还有更加优雅的方式来处理,请看: :: # 伪码 switch( sys.argv[1] ): case '-e': walk_cd() case '-d': search_cd() ... default: raise CommandException("Unknown Commend: " + sys.argv[1]) # 使用 if 替代 if sys.argv[1]=='-e': walk_cd() elif sys.argv[1]=='-d': search_cd() ... else: raise CommandException("Unknown Command: " + sys.argv[1]) # 更好的做法 commands = { '-e' : walk_cd, '-d' : search_cd, } try: commands[ sys.argv[1] ]() except KeyError: raise CommandException("Unknown Command: " + sys.argv[1]) 还记得上一章 python 数据类型中的习题 1 吗?我们要求读者用 and 和 or 操作符模拟 c 语言的 ? : 三元操作符。 实际上在 python2.5 以前,这确实是一个还算实用的技巧,不过 python2.5 中应广大 python 程序员的强烈呼吁, 终于加入了新的语法,终于可以用更优美的方式表达这种常用分支: TODO: 换成更有实际意义的例子 :: a = b*2 if b else default_value 等价于: :: if b: a = b*2 else: a = default_value 用 and or 技巧也可以写成: :: a = b and b*2 or default_value 显然是第一种写法看起来最顺眼了。 |
``elif`` 就是 ``else if`` 的缩写。 .. topic:: 没有 switch python 没有 ``switch`` 语句,因为觉得没必要,原因之一是 ``if elif else`` 组合已经足以应付大部分情况。 另外对于很大一部分的 ``switch`` 应用场景,python 还有更加优雅的方式来处理,请看: :: # 伪码 根据输入的不同参数选择程序的不同行为 switch( sys.argv[1] ): case '-e': walk_cd() case '-d': search_cd() ... default: raise CommandException("Unknown Commend: " + sys.argv[1]) # 使用 if 替代 if sys.argv[1]=='-e': walk_cd() elif sys.argv[1]=='-d': search_cd() ... else: raise CommandException("Unknown Command: " + sys.argv[1]) # 更好的做法 commands = { '-e' : walk_cd, '-d' : search_cd, } try: commands[ sys.argv[1] ]() except KeyError: raise CommandException("Unknown Command: " + sys.argv[1]) 最后一种方式不管从可读性(这是显然的)、性能(哈希表 vs 普通查找)上都高出很多。 另外最后一种做法将参数与行为的映射完全独立出来了,一来修改起来及其方便, 到时候也很容易将它们分离到配置文件中去。 .. topic:: 三元运算符 还记得上一章 python 数据类型的习题 1 吗?我们要求您用 and 和 or 操作符模拟 c 语言的 ? : 三元操作符。 实际上在 python2.5 以前,这确实是一个还算实用的技巧,不过 python2.5 中应广大 fans 的强烈要求, 终于加入了新的语法,从此可以用更优美的方式表达这种常用分支: TODO: 换成更有实际意义的例子 :: a = b*2 if b else default_value 等价于: :: if b: a = b*2 else: a = default_value 用 and or 技巧也可以写成: :: a = b and b*2 or default_value 不过显然是第一种写法看起来最顺眼了,不是吗 ;-) |
| Line 105: | Line 114: |
| for item in some_list: do something with item python 的 for 与 c 的 for 不同,要类比的话,大家可以想象一下某些语言的 foreach 。 python 只支持这一种 for 语句,而没有类似 c 的 for 语句, 因为用这种 for 语句很容易就可以模仿出 c 那种类型的 for 语句 (还记得上一章的习题2吧,对,就是它:range ;-): :: # 伪码,c 类型的 for 语句: for(i=0;i<10;i++): |
for item in [1, 2, 3]: print item 上面的代码其实就是遍历 ``some_list`` 列表,将其中每一个元素都打印出来。 所以的循环语句(其实也就是这里的 ``for`` 和后面的 ``while`` 了)中都可以使用这么两条语句: ``break`` 和 ``continue`` 。 ``break`` 表示要退出循环, ``continue`` 是说直接进入到下一轮 的循环中去吧: :: >>> for item in range(10): ... if item<5: # 遇到比 5 小的 ... continue # 进入下一轮循环 ... else: # 否则遇到的是大于等于 5 的 ... print item # 输出 ... break # 并直接退出循环 ... 5 上面这个例子中循环体本可以写成这样的::: if item>=5: print item break 不过为了照顾 ``continue`` 语句,我们就 ... 前面说过, ``for`` 语句后面可以跟 ``else`` 子句,它的意思就是说:如果 for 一直循环到了末尾 ,最后正常退出循环,那么随后就会执行它的 ``else`` 子句,否则由于 ``break`` 语句或异常等原因退出循环的, 则不会执行 ``else`` 子句。其实在程序中我们常常就会遇到这样的情况:对某个列表中每一个元素执行个什么操作, 如果成功执行则马上主动 ``break`` 跳出循环,如果遍历了整个列表,一直没有跳出循环,也就表示没有一个元素满足要求, 也就是失败了,那么希望在失败的情况下执行的语句呢就可以放在 ``else`` 子句中: :: >>> for item in range(10): ... if item<10: ... continue ... else: ... print item ... break ... else: ... print '没有大于等于10的数字' ... 没有大于等于10的数字 .. topic:: 迭代 如果你熟悉 c 语言的话,便会看出 python 的 for 和 c 的 for 的不同, 表面上的语法差异自然容易看出,但实际上他们的含义也是有比较大的不同的。 要类比的话,大家可以想象一下某些语言的 ``for in`` 或者某些语言的 ``foreach`` 。 用 c 的 for 模拟 python 的 for in 的话呢,大概(大概而已,有些本质的东西是不一样的) 是这个样子::: # python 的 for in for item in a_list: print item # c 的 for for(i=0; i<len(a_list); i++): print a_list[i] 其实用 ``for in`` 简单模拟 c 的 ``for`` 也是很容易的。 (还记得上一章的习题2吧,对,就是用它: ``range()`` ;-)::: # 伪码,c 类型的 for 语句: for(i=0;i<10;i++): ... # python 等价物: for i in range(10): ... 但其实两种 ``for`` 语句之间有一些重要的差别是无法用这种简单的模拟掩盖掉的。 那就是:迭代器! 通俗地讲, ``for`` 语句的形式有两种,一种就是取第0个、第1个、第2个,一直取到最后一个这样子。 另一种呢就是取下一个、取下一个、取下一个,这便是迭代器的行为,一直取到迭代器自己喊停为止。 c 语言只支持第一种,而 python 的 ``for in`` 可以同时支持这两种 ``for`` 形式! 我们先来解剖一下 python 的 ``for`` 语句::: for item in container: do_something(item) 对于上面的代码,如果 ``container`` 对象实现了 ``__getitem__`` 方法, 换句话说就是支持索引,那么这段代码等于是::: try: item = container[0] # 取第0个 # container[0] 其实就是调用了 container.__getitem__(0) 而已 do_something(item) item = container[1] # 取第1个 do_something(item) |
| Line 118: | Line 208: |
# python 等价物: for i in range(10): ... .. topic:: Under the hood :: for item in some_list: do some thing with item 实际上等价于: :: iterator = iter(some_list) |
except StopIteration: # 取到最后一个了(参见 异常处理_ ) pass 而如果 ``container`` 对象实现了 ``__iter__`` 方法,那它实际上又等价于::: iterator = iter(container) # 获取迭代器 # iter(container) 其实就是调用 container.__iter__() 而已。 |
| Line 135: | Line 216: |
| item = iterator.next() do some thing with item item = iterator.next() do some thing with item ... except StopIteration: |
item = iterator.next() # 取下一个 do_something(item) item = iterator.next() # 取下一个 do_something(item) ... except StopIteration: # 迭代器喊停了(参见 异常处理_ ) |
| Line 142: | Line 223: |
| 也就是说 for in 操作的是任意的迭代器! TODO: 关于迭代器! |
TODO:迭代器继续。。。 |
| Line 155: | Line 235: |
| #. 学习了几个流程控制的语法,体会 python 语法设计的简洁、正交。 #. 了解了所谓迭代器的概念 #. 知道了 __getitem__ 与索引的关系 |
|
| Line 158: | Line 244: |
| #. 使用 while 语句演示两种 for 语句的过程。 |
.. contents::
:status: 草稿 ;HuangYi; 40%;
===================
Python过程控制
===================
python 向来秉承简洁的设计原则,在语法的设计上体现得尤为明显!
稍有编程经验的朋友对下面这些语法应当不会陌生。
对于许多读者来说,可能只需要注意两点,本章的内容就可以飞快得浏览过去了:
一是 python 以缩进控制作用范围并且缩进都以冒号开头;
二是所有这些过程控制语句都可以跟个 ``else`` 子句!
``if`` 语句后面跟 ``else`` 自不必说,连 ``for`` 、 ``while`` 语句也可以跟 ``else`` 子句!
``else`` 子句的含义根据所处语句的不同自然也会有所不同。
if 分支
=========
最基本的用法:
::
if a == b:
print 'a 等于 b'
else:
print 'a 不等于 b'
也许你还需要更细致地控制:
::
if a == b:
print 'a 等于 b'
elif a < b:
print 'a 小于 b'
elif a > b:
print 'a 大于 b'
else:
print '在本宇宙中这是不可能滴!'
``elif`` 就是 ``else if`` 的缩写。
.. topic:: 没有 switch
python 没有 ``switch`` 语句,因为觉得没必要,原因之一是 ``if elif else`` 组合已经足以应付大部分情况。
另外对于很大一部分的 ``switch`` 应用场景,python 还有更加优雅的方式来处理,请看:
::
# 伪码 根据输入的不同参数选择程序的不同行为
switch( sys.argv[1] ):
case '-e':
walk_cd()
case '-d':
search_cd()
...
default:
raise CommandException("Unknown Commend: " + sys.argv[1])
# 使用 if 替代
if sys.argv[1]=='-e':
walk_cd()
elif sys.argv[1]=='-d':
search_cd()
...
else:
raise CommandException("Unknown Command: " + sys.argv[1])
# 更好的做法
commands = {
'-e' : walk_cd,
'-d' : search_cd,
}
try:
commands[ sys.argv[1] ]()
except KeyError:
raise CommandException("Unknown Command: " + sys.argv[1])
最后一种方式不管从可读性(这是显然的)、性能(哈希表 vs 普通查找)上都高出很多。
另外最后一种做法将参数与行为的映射完全独立出来了,一来修改起来及其方便,
到时候也很容易将它们分离到配置文件中去。
.. topic:: 三元运算符
还记得上一章 python 数据类型的习题 1 吗?我们要求您用 and 和 or 操作符模拟 c 语言的 ? : 三元操作符。
实际上在 python2.5 以前,这确实是一个还算实用的技巧,不过 python2.5 中应广大 fans 的强烈要求,
终于加入了新的语法,从此可以用更优美的方式表达这种常用分支:
TODO: 换成更有实际意义的例子
::
a = b*2 if b else default_value
等价于:
::
if b:
a = b*2
else:
a = default_value
用 and or 技巧也可以写成:
::
a = b and b*2 or default_value
不过显然是第一种写法看起来最顺眼了,不是吗 ;-)
for 循环
=========
::
for item in [1, 2, 3]:
print item
上面的代码其实就是遍历 ``some_list`` 列表,将其中每一个元素都打印出来。
所以的循环语句(其实也就是这里的 ``for`` 和后面的 ``while`` 了)中都可以使用这么两条语句:
``break`` 和 ``continue`` 。 ``break`` 表示要退出循环, ``continue`` 是说直接进入到下一轮
的循环中去吧:
::
>>> for item in range(10):
... if item<5: # 遇到比 5 小的
... continue # 进入下一轮循环
... else: # 否则遇到的是大于等于 5 的
... print item # 输出
... break # 并直接退出循环
...
5
上面这个例子中循环体本可以写成这样的:::
if item>=5:
print item
break
不过为了照顾 ``continue`` 语句,我们就 ...
前面说过, ``for`` 语句后面可以跟 ``else`` 子句,它的意思就是说:如果 for 一直循环到了末尾
,最后正常退出循环,那么随后就会执行它的 ``else`` 子句,否则由于 ``break`` 语句或异常等原因退出循环的,
则不会执行 ``else`` 子句。其实在程序中我们常常就会遇到这样的情况:对某个列表中每一个元素执行个什么操作,
如果成功执行则马上主动 ``break`` 跳出循环,如果遍历了整个列表,一直没有跳出循环,也就表示没有一个元素满足要求,
也就是失败了,那么希望在失败的情况下执行的语句呢就可以放在 ``else`` 子句中:
::
>>> for item in range(10):
... if item<10:
... continue
... else:
... print item
... break
... else:
... print '没有大于等于10的数字'
...
没有大于等于10的数字
.. topic:: 迭代
如果你熟悉 c 语言的话,便会看出 python 的 for 和 c 的 for 的不同,
表面上的语法差异自然容易看出,但实际上他们的含义也是有比较大的不同的。
要类比的话,大家可以想象一下某些语言的 ``for in`` 或者某些语言的 ``foreach`` 。
用 c 的 for 模拟 python 的 for in 的话呢,大概(大概而已,有些本质的东西是不一样的)
是这个样子:::
# python 的 for in
for item in a_list:
print item
# c 的 for
for(i=0; i<len(a_list); i++):
print a_list[i]
其实用 ``for in`` 简单模拟 c 的 ``for`` 也是很容易的。
(还记得上一章的习题2吧,对,就是用它: ``range()`` ;-):::
# 伪码,c 类型的 for 语句:
for(i=0;i<10;i++):
...
# python 等价物:
for i in range(10):
...
但其实两种 ``for`` 语句之间有一些重要的差别是无法用这种简单的模拟掩盖掉的。
那就是:迭代器!
通俗地讲, ``for`` 语句的形式有两种,一种就是取第0个、第1个、第2个,一直取到最后一个这样子。
另一种呢就是取下一个、取下一个、取下一个,这便是迭代器的行为,一直取到迭代器自己喊停为止。
c 语言只支持第一种,而 python 的 ``for in`` 可以同时支持这两种 ``for`` 形式!
我们先来解剖一下 python 的 ``for`` 语句:::
for item in container:
do_something(item)
对于上面的代码,如果 ``container`` 对象实现了 ``__getitem__`` 方法,
换句话说就是支持索引,那么这段代码等于是:::
try:
item = container[0] # 取第0个
# container[0] 其实就是调用了 container.__getitem__(0) 而已
do_something(item)
item = container[1] # 取第1个
do_something(item)
...
except StopIteration: # 取到最后一个了(参见 异常处理_ )
pass
而如果 ``container`` 对象实现了 ``__iter__`` 方法,那它实际上又等价于:::
iterator = iter(container) # 获取迭代器
# iter(container) 其实就是调用 container.__iter__() 而已。
try:
item = iterator.next() # 取下一个
do_something(item)
item = iterator.next() # 取下一个
do_something(item)
...
except StopIteration: # 迭代器喊停了(参见 异常处理_ )
pass
TODO:迭代器继续。。。
while 循环
============
异常处理
============
小结
==========
#. 学习了几个流程控制的语法,体会 python 语法设计的简洁、正交。
#. 了解了所谓迭代器的概念
#. 知道了 __getitem__ 与索引的关系
练习
===========
#. 使用 while 语句演示两种 for 语句的过程。
.. macro:: [[PageComment2(nosmiley=1, notify=1)]]