python基础教程_学习笔记7:条件、循环、其它语句
python基础教程_学习笔记7:条件、循环、其它语句
条件、循环、其它语句
print和import
随着更加深入地学习python,可能会出现这种感觉:有些自以为已经掌握的知识点,还隐藏着一些让人惊讶的特性。
使用逗号输出
打印多个表达式,只要将这些表达式用逗号隔开即可:
>>> print "age:",28
age: 28
参数之间都插入了一个空格符。
如果在结尾加上逗号,那么接下来的语句会与前一条语句在同一行打印:
print "Hello,",
print "World!"
结果:
Hello, World!
把某件事作为另一件事导入
从模块导入函数的时候,可以使用:
import somemodule
或
from somemodule import somefunction
或
from sommodule import somefunction,anotherfunction,yetanotherfunction
或
from somemodule import *
其中,只有确定自己想要从给定的模块导入所有功能时,才应该使用最后一个版本。
如果两个模块都有open函数,应该怎么做呢?
只需使用第一种方式导入,然后像下面这样使用函数:
module1.open(...)
module2.open(...)
但还有另外的选择:可以在语句末尾增加一个as语句,在该子句后给出名字,或为整个模块提供别名:
>>> import math as foobar
>>> foobar.sqrt(4)
2.0
也可以为函数提供别名:
>>> from math import sqrt as foobar
>>> foobar(4)
2.0
对于open函数,可以像下面这样使用:
from module1 import open as open1
from module2 import open as open2
赋值魔法
序列解包
多个赋值操作可以同时进行:
>>> x,y,z=1,23,456
>>> print x,y,z
1 23 456
用它交换两个(或多个)变量:
>>> x,y=y,x
>>> print x,y
23 1
>>> x,y,z=y,z,x
>>> print x,y,z
1 456 23
事实上,这里所做的事情叫做序列解包或可迭代解包——将多个值的序列解开,然后放到变量的序列中。
>>> values=1,2,3
>>> values
(1, 2, 3)
>>> x,y,z=values
>>> print x,y,z
1 2 3
当函数或者方法返回元组(或者其他序列或可迭代对象)时,这个特性尤其有用。假设需要获取(和删除)字典中的任意的键-值对,可以使用popitem方法,这个方法将键值对作为元组返回,那么这个元组可以直接赋值到两个变量中:
>>> people={'name':'signjing','age':'28','weight':'72'}
>>> x,y=people.popitem()
>>> print x,y
age 28
>>> x,y=people.popitem()
>>> print x,y
name signjing
>>> x,y=people.popitem()
>>> print x,y
weight 72
它允许函数返回一个以上的值并且打包成元组,然后通过一个赋值语句很容易进行访问。所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致,否则python会在赋值时引发异常:
>>> x,y=1,3,4
Traceback (most recent call last):
File "
x,y=1,3,4
ValueError: too many values to unpack
>>> x,y,z=2,9
Traceback (most recent call last):
File "
x,y,z=2,9
ValueError: need more than 2 values to unpack
链式赋值
链式赋值是将同一个值赋给多个变量的捷径。
x=y=somefunction()
和下面语句的效果是一样的:
y=somefunction()
x=y
注意:上面的语句和下面的语句不一定等价:
x=somefunction()
y=somefunction()
增量赋值
将表达式运算符放置在赋值运算符=的左边,这种写法叫做增量赋值,对于*、/、%等标准运算符都适用:
>>> x=5
>>> x+=3
>>> x*=2
>>> x/=4
>>> x
4
对于其他数据类型也适用(只要二元运算符本身适用于这些数据类型即可):
>>> s='too'
>>> s+='many'
>>> s*=2
>>> s
'toomanytoomany'
语句块
语句块是在条件为真(条件语句)时执行或执行多次的一组语句。在代码前放置空行来缩进语句即可创建语句块。
块中的每行都需要缩进相同的量。
很多语言使用特殊单词或者字符(比如begin或{)来表示一个语句块的开始,用另外的单词或字符(如end或})表示语句块的结束。
在python中,冒号(:)用来标识语句块的开始,块中的每一个语句都是缩进的(缩进量相同)。当回退到和已经闭合的块一样的缩进量时,就表示当前块已经结束了。
条件和条件语句
布尔变量
下面的值在作为布尔表达式时候,会被解释看做假(False):
False None 0 “” () [] {}
换句话说,也就是标准值False和None、所有类型的数字0(包括浮点数、长整型和其它类型)、空序列(比如空字符串、元组和列表)以及空的字典都为假。其它的一切都解释为真,包括特殊值True。
标准的真值为True和False。事实上,True和False只不过是1和0的“华丽”说法而已。
>>> True
True
>>> False
False
>>> True==0
False
>>> True==1
True
>>> False==0
True
>>> False==1
False
>>> False+True+23
24
布尔值True和False属于布尔类型,bool函数可以用来(和list、str以及tuple一样)转换其它值。
>>> bool('I think ,therefore I am')
True
>>> bool(42)
True
>>> bool(0)
False
>>> bool('')
False
>>> bool(False)
False
>>> bool(())
False
>>> bool({})
False
>>> bool([])
False
因为所有值都可以用作布尔值,所以几乎不需要对它们进行显式转换(可以说python会自动转换这些值)。
注意:尽管[]和””都是假植(也就是说bool([])==bool(“”)==False),它们本身并不相等。对于其他不同类型的假值对象也是如此(例如,()!=False)。
条件执行和if语句
if语句可以实现条件执行,如果条件判定为真,则后面的语句块执行,如果条件为假,语句块就不会被执行。
name=raw_input("Please input a name: ")
if name.endswith("Bob"):
print "Hello,Bob!"
如果用户输入了以Bob结尾的名字,则打印出问候语。
else语句
else子句(之所以叫子句,是因为它不是独立的语句,而只能作为if语句的一部分)可以增加一种选择。
name=raw_input("Please input a name: ")
if name.endswith("signjing"):
print "Hello,signjing!"
else:
print "Hello,someone!"
如果第1个语句块没有被执行,则转入第2个语句块。
elif语句
如果需要检查多个条件,就可以使用elif,它是“else if”的简写,也是if和else子句的联合使用——也就是具有条件的else子句。
num=input("Please input a num: ")
if num>0:
print "num > 0"
elif num<0:
print "num < 0"
else:
print "num = 0"
嵌套代码块
if语句里可以嵌套使用if语句:
num = input("Please input a num: ")
if num > 0:
if num >5:
print "num > 5"
elif num > 3:
print "num >3 and num <= 5"
else:
print "num <= 3 and num > 0"
elif num < 0:
if num < -10:
print "num < -10"
elif num < -4:
print "num < -4 and num >= -10"
else:
print "num >= -4 and num < 0"
else:
print "num = 0"
更复杂的条件
比较运算符
表达式 描述
x==y x等于y
x x>y x大于y x>=y x大于等于y x<=y x小于等于y x!=y x不等于y x is y x和y是同一个对象 x is not y x和y是不同的对象 x in y x是y容器的成员 x not in y x不是y容器的成员 理论上,对于相对大小的任意两个对象x和y都是可以使用比较运算符比较的,并且都会得到一个布尔值结果。但是只有在x和y是相同或者近似类型的对象时,比较才有意义。 在python中比较运算和赋值运算一样是可以连接的——几个运算符可以连在一起使用: >>> a=5 >>> 0
True >>> 0
False >>> 03 True 想要知道两个东西是否相等,应该使用相等运算符,即两个等号==: >>> "abc"=="abc" True >>> "abc"=="Abc" False 单个相等运算符是赋值运算符,是用来改变值的,不能用来比较。 这个运算符比较有趣,它看起来和==一样,但事实上却不同: >>> x=y=[1,2,3] >>> z=[1,2,3] >>> x==y True >>> x is y True >>> x == z True >>> x is z False x和z相等却不等同,因为is运算符是判定同一性而不是相等性。 x和y被绑定到同一个列表上,而变量z被绑定在另外一个具有相同数值和顺序的列表上。它们的值可能相等,但却不是一个对象。 之前说明过了,此处略; 字符串可以按照字母顺序排列进行比较。 >>> "a" < "b" True >>> "abc" < "ab" False 注意:实际的顺序可能会因为使用不同的locale而和上面的例子有所不同。 其他的序列也可以以相同的方式进行比较,不过比较的不是字符而是元素的其它类型: >>> [1,2,4]>[1,2,3] True >>> [1,2,[2,'a']]<[1,2,[3,4]] True and运算符,连接两个布尔值,且在两者都为真时返回真,否则返回假。 or运算符,连接两个布尔值,且在两者都为假时返回假,否则返回真。 not运算符,连接一个布尔值,当连接的布尔值为真时返回假,为假时返回真。 x and y需要两个变量都为真时才为真,如果x为假,则x and y立即返回false,而不需计算y的值。同理,x or y只要有一个为真则为真,如果x为真,则x or y直接返回True,而不需计算y的值。这样,避免了无用地执行代码,可以作为一种技巧使用。 if语句有个非常有用的近亲,其工作方式多少有点像下面这样(伪代码): if not condition: crash program 这样做是因为与其让程序在晚些时候崩溃,不如在错误条件出现时直接让它崩溃。一般来说,你可以要求某些条件必须为真。语句中使用的关键字为assert。 >>> age=10 >>> assert 0
>>> age=-2 >>> assert 0
Traceback (most recent call last): File " assert 0
AssertionError 如果需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert语句就有用了,可以在程序中置入检查点: 条件后可以添加字符串(用逗号把条件和字符串隔开),用来解释断言: >>> assert 0
Traceback (most recent call last): File " assert 0
AssertionError: make age right 用来在任何条件为真的情况下重复执行一个代码块。 i=5 while i>0: print i i-=1 结果: 5 4 3 2 1 list1=list('signjing') for l in list1: print l 结果: s i g n j i n g numbers=[1,2,3,4] for n in numbers: print n 结果: 1 2 3 4 迭代(循环的另一种说法)某个范围的数字是很常见的,有个内建的函数可供使用: for n in range(1,5): print n 结果: 1 2 3 4 range函数的工作方式类似于分片,包含下限,不包含上限,如果希望下限为0,则可以只提供上限。 提示: 如果能使用for循环,就尽量不使用while循环。 一个简单的for语句就能循环字典的所有键,就像处理序列一样: d={'x':1,'y':2,'z':3} for key in d: print key,d[key] 结果: y 2 x 1 z 3 for循环的一大好处就是可以在循环中使用序列解包: d={'x':1,'y':2,'z':3} for key,value in d.items(): print key,value 结果: y 2 x 1 z 3 在python中迭代序列(或其它可迭代对象)时,一些函数非常有用。有些函数位于itertools模块,还有些python的内建函数也十分有用。 程序可以同时迭代两个序列: names=['anne','beth','damon'] ages=[13,19,21] for i in range(len(names)): print names[i],'is',ages[i],'years old.' 结果: anne is 13 years old. beth is 19 years old. damon is 21 years old. 内建的zip函数可以用来进行并行迭代,把两个序列“压缩”在一起,然后返回一个元组的列表: names=['anne','beth','damon'] ages=[13,19,21] for name,age in zip(names,ages): print name,"is",age,"years old." 结果: anne is 13 years old. beth is 19 years old. damon is 21 years old. zip函数可以作用于任意多的序列。关于它很重要的一点是zip可以应付不等长的序列:当最短的序列“用完”的时候就会停止: >>> zip(range(5),xrange(100)) [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] >>> zip(range(5),xrange(2)) [(0, 0), (1, 1)] 有些时候想要迭代序列中的对象,同时还要获取当前对象的索引。 暂略; reversed和sorted,同列表的reverse和sort方法类似,但作用于任何序列或可迭代对象上,不是原地修改对象,而是返回翻转或排序后的版本: >>> sorted([4,3,6,8,3]) [3, 3, 4, 6, 8] >>> sorted('hello,world!') ['!', ',', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w'] >>> list(reversed('hello,world!')) ['!', 'd', 'l', 'r', 'o', 'w', ',', 'o', 'l', 'l', 'e', 'h'] >>> ''.join(reversed('hello,world')) 'dlrow,olleh' 结束循环可以使用break语句。 for i in range(5): print i if i > 2: break print "--" 结果: 0 -- 1 -- 2 -- 3 continue语句用的要少很多,它让当前的迭代结束,“跳”到下一轮循环的开始。基本意思是:跳过剩余的循环体,但不结束循环。当循环体很大而且很复杂时,会很有用。 for i in range(5): print i if i > 2: continue print "--" 结果: 0 -- 1 -- 2 -- 3 4 while True实现了一个永远不会自己停止的循环,但在循环体内部的if语句中加入条件,在条件满足时调用break语句。这样,就可以在循环内部任何地方而不是只在开头终止循环。 尽管应该小心在代码中频繁使用break语句,但这个特殊的技术用得非常普遍。 当在循环体内部使用break语句时,通常是因为找到了某物或某事发生了,在跳出时做一些事情是简单的,但有些时候想要在没有跳出之前做些事情。可以在循环中增加一个else语句——仅在没有调用break时执行。 for i in range(5): print i if i > 6: break print "--" else: print "I'm here" 结果: 0 -- 1 -- 2 -- 3 -- 4 -- I'm here for和while循环中都可以使用continue、break语句和else子句。 列表推导式是利用其它列表创建新列表的一种方法。工作方式类似于for循环。 >>> [x*x for x in range(1,6)] [1, 4, 9, 16, 25] 可以增加判断条件: >>> [x*x for x in range(1,6) if x%2==0 ] [4, 16] 可以增加更多的for语句: >>> [x*y for x in range(1,3) for y in (2,5)] [2, 5, 4, 10] 也可以和if语句联合使用: >>> [x*y for x in range(1,11) for y in range(1,9) if x%3==0 if y%4==0 ] [12, 24, 24, 48, 36, 72] 注意:for循环部分和if语句部分之间都没有标点符号。 有些时候,程序什么事情都不用做: >>> pass >>> name=raw_input("Please input a name: ") if name == 'signjing': print "I'm signjing" elif name == 'sj': pass else: print "unknown" 执行: Please input a name: signjing 结果: I'm signjing 执行: Please input a name: sj 如果将pass行注释: if name == 'signjing': print "I'm signjing" elif name == 'sj': #pass else: print "unknown" 执行报错: File "pass.py", line 6 else: ^ IndentationError: expected an indented block 一般来说,python解释器(以其无穷的智慧)自动删除那些不再使用的对象。另一种方法是使用del语句,它不仅会移除一个对象的引用,也会移除那个名字本身。 >>> x=['hello','world'] >>> y=x >>> y[1]='python' >>> x ['hello', 'python'] >>> del x >>> y ['hello', 'python'] 事实上,python中是没有办法删除值的,因为值不再使用时,python解释器会负责内存的回收。 有些时候会动态地创造python代码,然后将其作为语句执行或作为表达式计算,这近似于“黑暗魔法”——在此之前,一定要慎之又慎,仔细考虑: 执行一个字符串的语句是exec: >>> exec "print 'hello'" hello 但使用简单形式的exec语句绝不是好事。很多时候可以给它提供命名空间——可以放变量的地方。 >>> from math import sqrt >>> exec "sqrt = 1" >>> sqrt(4) Traceback (most recent call last): File " sqrt(4) TypeError: 'int' object is not callable 可以通过in >>> from math import sqrt >>> scope={} >>> exec "sqrt = 1" in scope >>> sqrt(4) 2.0 >>> scope['sqrt'] 1 可见,潜在的破坏性代码并不会覆盖sqrt函数,原来的函数能正常工作,而通过exec赋值的变量sqrt只在它的作用域内有效。 注意,如果需要将scope打印出来的话,能看到其中包括很多东西,因为内建的__builtins__字典自动包含所有的内建函数和值: >>> len(scope) 2 >>> scope.keys() ['__builtins__', 'sqrt'] eval(用于“求值”)是类似于exec的内建函数。 exec语句会执行一系列的python语句,而eval会计算python表达式,并返回结果值。 exec语句并不返回任何对象,因为它本身就是语句。 >>> eval(raw_input("Enter an arithmetic expression: ")) Enter an arithmetic expression: 2*6+8 20比较不兼容类型
相等运算符
is:同一性运算符
in:成员资格运算符
字符串和序列比较
布尔运算符
短路逻辑
断言
循环
while循环
for循环
循环遍历字典元素
一些迭代工具
并行迭代
编号迭代
翻转和排序迭代
跳出循环
break
continue
while True/break习语
循环中的else子句
列表推导式——轻量级循环
三人行
什么都没发生
使用del删除
使用exec和eval执行和求值字符串
exec
eval
评论关闭