第05章 | 条件、循环和其他语句
------
print 和 import
#如果要打印多个语句,用,分割
>>> print "Name is:","Sherry.","Age is:",40 Name is: Sherry. Age is: 40 >>> print (1,2,3) #如果要打印元祖 (1, 2, 3) >>> print 1,2,3 #print语句会在每个元素间插入一个空格 1 2 3
#如果想同时输出文本和变量,却又不希望用格式化的方法,那么就非常有用了。
>>> greeting = 'Hello,' >>> salutation = 'Mr' >>> name = 'Smith.' >>> print greeting, salutation, name Hello, Mr Smith.
#如果‘‘中不加入逗号,要如何实现呢
>>>print greeting + ',', salutation, name
#如果在结尾处加上,下一句会接着上一句打印
print 'Hello,', print 'World!' 输出结果: Hello,World!
Note:
1. 在很多应用程序中用logging模块记日志比print更合适
2. 在Python3.0上,print时函数,所以要用print(‘Hello,World!‘)这种方式.
------
事件导入
#导入某个模块 import somemodule #从某个模块中导入某个函数 from somemodule import somefunc #从某个模块中导入多个函数 from somemodule import func1, func2,func3 #从某个模块中导入所有函数 from somemodule import * #如两个模块都有一个函数open module1.open() module2.open() #加as子句提供别名功能 >>> import math as foobar >>> foobar.sqrt(4) 2.0 #也可以在函数后面加as语句,为函数提供别名 >>> from math import sqrt as foobar >>> foobar(4) 2.0 #如果两个模块同时又某个函数,可以分别提供别名: from module1 import open as open1 from module2 import open as open2
------
序列解包
>>> x,y,z=1,2,3 #多个赋值 >>> x,y,z (1, 2, 3) >>> x,y=y,x #两个交换 >>> x,y,z (2, 1, 3)
上述操作就叫序列解包:将多个值的序列解开,然后放到变量的序列中
>>> values = 1,2,3 >>> values (1, 2, 3) >>> x,y,z = values >>> x 1
当函数或方法返回元祖时,这个特性尤其有用,假如想获取或删除某个字典中的任意键值,
可以用popitem(),但要如果获取键/值呢?可以存放在两个变量中.
>>> d={'name':'Sherry','age':40} >>> key,value=d.popitem() >>> key 'age' >>> value 40
解包元素的数量必须和变量个数一致,否则要报错:
>>> x,y,z=1,2 Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: need more than 2 values to unpack >>> x,y,z=1,2,3,4 Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: too many values to unpack
Note:Python3.0中有个特性,允许两边数量不一致
>>> a,b,rest*=[1,2,3,4] >>> a;b 1 2 >>>rest #多余的元素都收集到了rest [3,4]
------
链式赋值:
将同一值赋给多个变量的捷径
x = y = func()
和下面的语句效果是一样的
y = func()
x = y
但上面的语句和下面的语句不一定是等价的.
x = func()
y = func()
------
增量赋值
x = x+1; 也可以 x +=1,对于其他的操作符-,*,/,%都适用
一般来说+=这样执行的要优于前者
>>> x = 1 >>> x +=1 >>> x *=2 >>> x 4
#对于其他数据类型也适用
>>> s = 'She' >>> s +='rry' >>> s *=2 >>> s 'SherrySherry'
Note: 增量赋值让代码更加紧揍,简练,更加易读
------
语句块:
- 是条件为真的,一组语句块
- :标示语句块的开始
- 块的语句都是缩进的
- 等量缩进
- 可以用Tab进行缩进,但Python强烈建议用4个空格做为缩进
------
布尔变量的作用
下面的值在布尔表达式中,会被python解释器看成为假(False)
- False
- 0
- None
- ""
- []
- ()
- {}
换句话说,False和None,及所有的数字类型0(整型,浮点型)所有的空序列(字符串,列表,元祖),空字典
这点非常有用
>>> False == 0 True >>> True True >>> False False >>> True == 1 True >>> True + False +42 43
#在这里True==1,False==0
#所以条件判断的时候, if True: 或 if 1: 都可以作为判断的条件
#True,False是布尔值,bool函数可以用来转换为布尔值
>>> bool('I think, therefor i am.') True >>> bool(42) True >>> bool('') False >>> bool(0) False
#因为所有值都可以用作布尔值,所以Python不需要转换,会自动转换。
>>> if bool(42): #所以像这样其实是没有必要的 ... print "Hello,World!" ... Hello,World!
------
条件执行及if语句:
#大多教程,大多说法,条件真假的区别
>>> name=raw_input('Enter your name:') Enter your name:ni hao Jerry >>> if name.endswith('Jerry'): #条件为真,语句执行,为假,语句不执行 ... print "Hi,Jerry!" ... Hi,Jerry!
#也有人认为这是"有些东西"和"没有东西"的区别
------
else语句:
条件为真执行if语句块,否则执行else语句块
>>> name=raw_input("What's your name:") What's your name:John smith >>> if name.startswith('John'): ... print 'Hi, John!' ... else: ... print 'Hi, Strange.' ... Hi, John!
------
elif:
如果要检查多个条件,则要用到elif
>>> num=input('Enter a number:') Enter a number:1 >>> if num > 0: ... print "num is a postive" ... elif num < 0: ... print "num is a negative." ... else: ... print "num is zero." ... num is a postive
Note: int(raw_input())来代替input
------
嵌套代码块
if语句嵌套使用if语句
# cat hello1.py #!/usr/bin/env python name = raw_input('What is your name:') if name.endswith('John'): if name.startswith('Mr.'): print 'Hello,Mr.John.' elif name.startswith('Mrs.'): print 'Hello,Mrs.John.' else: print 'Hello,John.' else: print "Hello,Strange." # ./hello1.py What is your name:John Hello,John.
------
更复杂的条件
1.比较运算符
Note:
1. x <> y 表示 x != y. 不建议使用此运算符.
2. 不同类型比较,Python版本不同,可能出问题。尽量避免
3. 比较对象的时候可以用内建的函数cmp()
2.
相等运算符:
>>> 'foo' == 'foo' True >>> 'foo' == 'bar' False >>> 'foo' = 'foo' SyntaxError: can't assign to literal
== 表示相等
= 赋值
3.
is 同一性运算符号:
>>> x = y = [1,2,3] >>> z = [1,2,3] >>> x == y True >>> x == z True >>> x is y True >>> x is z False >>> id(x);id(y);id(z) 47564308846784 47564308846784 47564308846856
#is 是判断同一性,而不是相等性。
#值相等,但确不是同一个对象,如果还不明白的话,可以看下面的例子
>>> x = [1,2,3] >>> y = [2,4] >>> x is not y True >>> del x[2] >>> y[1]=1 >>> y.reverse() >>> y [1, 2] >>> x is y #显然两个列表不等同 False
总结 :用==来判断两个对象的值是否相等
用is来判断两个对象是否是同一对象
WARN:避免将is用于比较数值或字符串这些不可变值。
由于Python内部操作这些对象方式的原因,使用is运算符其结果是不可测的。
------
in
成员关系运算符
>>> name=raw_input(r'Enter your name:') Enter your name:Jerry >>> if 'J' in name: ... print "Your name contains 'J'" ... else: ... print "Your name not contains'J'" ... Your name contains 'J'
------
5.
字符串和序列比较
>>> 'alpha'<'beta' True #如果顺序比较凌乱的话,用upper(),或者lower()先来转化,再比较 >>> 'JErrY'.upper() == 'jerrY'.upper() True >>> [1,2]<[2,1] True >>> [2,[1,4]]<[2,[1,5]] True
6. 布尔运算符
如果要写个小程序:写1到10之间的数并比较
number=input('Enter a number between 1 and 10:') if number <=10: if number >= 1: print 'Correct.' else: print 'Wrong.' else: print 'Wrong.'
上面的方法就有重复行,因此要合并下:
number=input('Enter a number between 1 and 10:') if number<=10 and number>=1: print "Correct" else: print "Wrong."
Note: 或者这样写 if 1<= number <= 10:
and
,or, not 三个布尔运算符,可以随意组合真值
if ((crash>price) or customer_has_good_credit) and not out_of_stock: give_goods()
短路逻辑及条件表达式
x
and y: 前面条件为真才会继续后面的判断
x or y: 前面为真,返回x的值,否则返回y的值
作用: 主要避免了无用执行代码,可以作为一种技巧,假如用户应该输入用户名,
但用户可以选择不输入,这时可以使用默认值‘<unknown>‘,使if语句更加简洁
>>> name=raw_input('Enter your name:') or '<unknown>' Enter your name: >>> print name <unknown>
------
端言:
assert
if not condition:
crash program
为什么需要出现此种代码,这是因为与其让程序在晚些时候崩溃,不如在错误条件出现
时就直接让它崩溃,一般来说,你可以要求条件必须为真
(例如,在检查函数参数的属性时,或者作为初期测试和调试过程中的辅助条件).
>>> age = 10 >>> assert 0< age <100 >>> age = -1 >>> assert 0< age <100 Traceback (most recent call last): File "<stdin>", line 1, in ? AssertionError
如果需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert语句就有欧诺个了。
它可以在程序中置入检查点。条件后可以添加字符串,用来解释断言:
>>> age = -1 >>> assert 0< age <100, 'The age must between 1-100' Traceback (most recent call last): File "<stdin>", line 1, in ? AssertionError: The age must between 1-100
------
循环:
如果要打印1-100,不可能
print 1
print 2
......
print 100 这里就要用到循环
While循环
>>> x = 1 >>> while x<=100: ... print x ... x +=1
name = '' while not name: # name,空则为假,not name: 则为真。 name = raw_input('Enter your name:') print 'Hello,%s!' % name
# 如果再次输入空值,程序会要求你重新输入
# 如果输入姓名有空格,则可以while not name.strip():来除掉空格;
------
for
循环
while 循环很灵活,只要条件为真就会一直执行.但如果是一个集合(序列和其他可迭代对象)
每个元素都执行一个代码块,就要考虑用到for循环.
Note: 可迭代对象指可以按次序迭代的对象
>>> words = ['My','name','is','Mrs','Alice'] >>> for word in words: ... print word ... My name is Mrs Alice
或者
>>> numbers = [1,2,3,4,5,6,7,8,9] >>> for number in numbers: ... print number, ... 1 2 3 4 5 6 7 8 9
或者
>>> for number in range(10): ... print number, ... 0 1 2 3 4 5 6 7 8 9
xrange: 类似于range,返回个迭代对象,在巨大序列时会更高效,一般情况,不必过多关注
注意:如果能用for循环的话,就尽量不用while循环
------
循环遍历字典元素
>>> for key in d: ... print key, 'corresponds to', d[key] ... y corresponds to 2 x corresponds to 1 z corresponds to 3
或者
>>> d = {'x':1,'y':2,'z':3} >>> d.items() [('y', 2), ('x', 1), ('z', 3)] >>> for key,value in d.items(): ... print key,'corresponds to',value ... y corresponds to 2 x corresponds to 1 z corresponds to 3
Note: 字典是无序的,如果顺序很重要的话,可以讲键值保留在单独的列表中;例如在迭代前排序.
------
一些迭代工具:
Python内建函数或itertools模块
并行迭代:
>>> name = ['Jerry','Wendy','Alice'] >>> age = [40,30,20] >>> for i in range(len(name)): ... print name[i],'is', age[i],'years old.' ... Jerry is 40 years old. Wendy is 30 years old. Alice is 20 years old.
#或者用序列包的方式来迭代
>>> name = ['Jerry','Wendy','Alice'] >>> age = [40,30,20] >>> for name,age in zip(name,age): #循环中解包元祖 ... print name,'is',age,'years old.' ... Jerry is 40 years old. Wendy is 30 years old. Alice is 20 years old.
#zip可以合并不等长队列,以最小为准备
>>> zip(range(5),xrange(100000)) [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
Note:不推荐用range来代替xrange,
>>> zip(range(5),xrange(100000000)) #遍历所有的数字,速度很慢 [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] >>> zip(range(5),range(100000000)) #速度很快 [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
------
翻转和排序迭代
>>> sorted([3,6,4,3,8]) [3, 3, 4, 6, 8] >>> sorted('A B C D') [' ', ' ', ' ', 'A', 'B', 'C', 'D'] >>> reversed('A B C D') <reversed object at 0x0000000001D8EF28> >>> list(reversed('A B C D')) ['D', ' ', 'C', ' ', 'B', ' ', 'A'] >>> ''.join(reversed('A B C D')) 'D C B A'
------
跳出循环
Break:
结束循环
假设寻找100以内最大平方数,找到了则break循环
>>> for n in range(99,0,-1): root = sqrt(n) if root == int(root): print root break 9.0
range(99,0,-1)步长为-1,反向迭代
>>> range(0,10,2) #步长为2 [0, 2, 4, 6, 8] >>> range(10,0,-2) #步长为-2,反向迭代 [10, 8, 6, 4, 2]
continue:结束当前的循环,返回下一次迭代的开始:
最基本的意思: 跳过剩余的循环体,但是不结束循环.
for x in seq: if condition1: continue if condition2: continue do something() do anotherthing()
------
word='dummy' while word: word=raw_input('Enter your name:') print 'word is:', word [[email protected] python]# ./while.py Enter your name:Jerry word is: Jerry Enter your name:Tom word is: Tom
上面一段代码赋了一个哑值(未使用的值),这是程序应该完善的地方
word=raw_input('Enter word here:') while word: print 'Word is:',word word=raw_input('Enter your name:')
#这样做的好处是:哑值不见了,而且输入一个空值会跳出循环,while True/break
while True: word=raw_input('Enter word:') if not word: break print 'word is:', word
尽量避免在代码中多次使用while True/break,会降低代码的可读性。但while True/break,的确是非常有用。
-----------
循环中的else子句:
from math import sqrt for n in range(99,81,-1): root = sqrt(n) if root == int(root): print n break else: print "Don't find it."
--------
列表推导式-轻量级循环
列表推导式--利用其它列表来创造新的列表
>>> [x*2 for x in range(5)] [0, 2, 4, 6, 8] >>> [x*x for x in range(5)] [0, 1, 4, 9, 16] >>> [x*x for x in range(10) if x%3==0] [0, 9, 36, 81]
#增加更多for语句的部分
>>> [(x,y) for x in range(2) for y in range(4)] [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3)]
#可以用下面双重循环来遍历,但无疑上面代码要简洁些
>>> for x in range(2): ... for y in range(4): ... result.append([x,y]) ... >>> result [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 1], [1, 2], [1, 3]]
#也可以用if子句来联合,比如说找出boys,girls中首字母相同的单词:
>>> boys = ['tom','bob'] >>> girls = ['alice','bernice'] >>> [b+'+'+g for b in boys for g in girls if b[0]==g[0]] ['bob+bernice']
Note:()得不到元祖推导式,只有[]才可以.
pass:如果程序上面都不用做,pass就要用上,某种程度,pass是调试程序或防止程序用的
比如:
if name='Alice' print "Welcome Alice." elif name='Bob' #还没完 elif name='Jerry' print 'Access deny.'
这个时候中间就要用到pass,否则程序在判断name=‘Bob‘会报错
if name='Alice' print "Welcome Alice." elif name='Bob' #还没完 pass elif name='Jerry' print 'Access deny.'
Note:注释和pass联合使用的替代方案是插入字符串,对于那些没有完成的函数和类,这个方法尤其有用,
因为它们扮演文档字符串的角色.
print ''' The function part still not completed, needed to add something here: '''
del
#d1,和d2绑定在同一个字典里,如果d1设置为None,字典通过d2还是可用的,如果d2也设置为None,那么字典
就漂在内存,没法获取和使用她。直到删除那个字典:
>>> d1 = {'name':'John','age':40} >>> d2 = d1 >>> d1 = None >>> d2 {'age': 40, 'name': 'John'} >>> d1 >>> d2 = None
#移除一个对象,同时移除那个名字本身
>>> x = 1 >>> del x >>> x Traceback (most recent call last): File "<stdin>", line 1, in ? NameError: name 'x' is not defined
# x, y 指向同一个列表,删除的只是x名称,本身的值并没有删除
>>> x = ['hello','world'] >>> y = x >>> y[1] = 'python' >>> x ['hello', 'python'] >>> del x >>> y ['hello', 'python'] 比如说: >>> x = y = 1 >>> del x >>> y 1 >>> del x,y #如果要删除多个值,可以这样
#当然也可以重写函数默认的del函数来删除对象
------
使用exec和eval执行和求值字符串
#类似于shell中的exec和eval
>>> exec "print 'Hello,world!'" Hello,world!
# python3.0中,exec是函数不是语句
------
eval(用于求值)
>>> eval(raw_input('Enter arithmetic expression:')) Enter arithmetic expression:6+18*2 42 #eval(raw_input()) == input >>> input('Enter arithmetic expression:') Enter arithmetic expression:6+18*2 42
#python3.0 中已经用input来替代raw_input()
--------
本章新函数
chr(n) 当传入序号为n时,返回n所代表的包含一个字符的字符串
eval(source[,global[,local]]) 将字符串作为表达式计算,并返回值
emumerate(seq) 产生用于迭代的(索引,值)对
ord(c) 返回单字符的值
range() 返回整数的列表
reversed(seq) 产生seq的反向版本,用于迭代
xrange() 创造xrange对象,用于迭代
zip(seq1,seq2) 创造用于并行迭代的新序列