条件、循环和其他语句

2016-12-07 · 🙈Lei · 0条 · 502次

>_ print函数(print不应该出现在这篇文章中,因为Python3中print已经不是语句,而是一个函数)

print可以用来打印表达式,不管是字符串还是其他类型进行自动转换后的字符串。该函数可以用来打印多个表达式,只需要用逗号隔开。打印出的结果中,每个参数间被插入了一个空格符。

>>> print(1,2,3) 1 2 3 
>>> print((1,2,3)) (1, 2, 3) 

>_ 导入时指定别名

导入模块/函数时可以在语句末增加一个as子句,在该子句后给出想要使用的别名。

>>> import math as footer 
>>> footer.sqrt(4) 2.0 
>>> from math import sqrt as foot 
>>> foot(4) 2.0 

>_ 赋值

1.序列解包

多个赋值操作可以同时进行:

>>> x,y,z = 1,2,3 
>>> print(x,y,z) 1 2 3 

交换两个(或更多个)变量:

>>> x,y = y,x 
>>> print(x,y,z) 2 1 3 

这就叫做序列解包或递归解包——将多个值的序列解开,然后放到变量的序列中。形象的表示是:

>>> values = 1,2,3 
>>> values (1, 2, 3) 
>>> x,y,z = values >>> print(x,y,z) 1 2 3 

当函数或者方法返回元组(或者其他序列或可迭代对象)时,这个特性尤为重要。它允许函数返回一个以上的值并且打包成元组,然后通过一个赋值语句很容易进行访问。

所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致,否则Python会在赋值时引发异常。

在Python3.0中还有一个特性,可以使用*运算符,将多余的值全部赋给某个变量。

>>> a,b,*rest = [1,2,3,4]
>>> rest
[3, 4]
>>> *rest,a,b = [1,2,3,4]
>>> rest
[1, 2]
>>> a
3
>>> b
4
>>> a,b,*rest1,*rest2 = [1,2,3,4,5,6,7]
SyntaxError: two starred expressions in assignment
>>> a,b,*rest1,rest2 = [1,2,3,4,5,6,7]
>>> rest1
[3, 4, 5, 6]
>>> rest2
7

2.链式赋值

链式赋值是将同一个值赋给多个变量的途径。

x=y=somefunction()

相当于

y = somefunction()

x = y

但不一定等价于

y = somefunction()

x = somefunction()

3.增量赋值

将表达式运算符(二元运算符)放到赋值运算符的左边,+、-、*、/、%等标准运算符都适用。只要二元运算符本身适用于这些数据类型即可。

>>> a = 'hello' 
>>> a += 'ray' 
>>> a 'helloray' 
>>> a *= 2 
>>> a 'hellorayhelloray' 

>_ 语句块

在Python中,冒号(:)用来标识语句块的开始,块中的每一个语句都是缩进的(缩进量相同)。当回退到和已经闭合的块一样的缩进量时,表示当前块已经结束了。

>_ 条件和条件语句

1.布尔值(真值)是以George Boole命名的,下面的值作为布尔表达式的时候,会被解释器看作假(false):

False None 0 "" () [] {}

标准值False和None,所有类型的数字0(包括浮点型、长整型和其他类型),空序列(比如空字符串、元组和列表)以及空的字典都为假。

2.布尔值True和Flase属于布尔类型,bool可以用来转换其他值。因为所有值都可以用作布尔值,所以不需要进行显示转换。

>>> bool(21) True 
>>> bool(0) False 
>>> bool([]) False 
>>> bool([1,2,3]) True 

3.if: else:

elif是else if的缩写。

4.比较运算符

x is y x和y是同一个对象

x is not y x和y是不同的对象

x in y x是容器y的成员

x not in y x不是容器y的成员

在python3.0之前的版本中对于任意大小的两个对象的比较都是可以的,但是不一定有意义,例如比较一个整型和一个字符串,但是在3.0之后,不兼容类型的对象已经不能比较。

在python中比较运算符是可以连在一起使用的,例如0<x<100

5.is同一性运算符

is是用来判定同一性的,而不是相等性。

避免将is运算符用于比较类似数值和字符串这类不可变值。

6.字符串和序列比较

字符串可以按照字母顺序进行比较,实际的顺序可能会因为使用不同的本地化设置(locale)而有所不同。

>>> 'alpha' < 'beta' True 

一个字母的顺序值可以用ord函数查到,ord函数和chr函数功能相反。

>>> chr(86) 'V' 
>>> ord('a') 97 

对于其他序列也是类似的比较方法。

>>> (1,2,(1,2)) < (1,2,(2,2)) True 

7.布尔运算符

and, or, not

布尔运算符有个有趣的特性:只有在需要求值时才进行求值。x and y,如果x为false,就会立刻返回false,不会管y的值。实际上是,如果x为假,表达式就会返回x的值,否则就会返回y的值,这种行为被称为短路逻辑或惰性求值。

这主要是为了避免无用地执行代码,可以作为一种使用技巧,假设用户需要输入名字,但是也可以选择什么都不输入,这时可以使用默认值“<unknown>”,可以写成:

name = input('please enter your name:') or '<unknown>'

如果前段部分返回值为真(不是空字符串),就会赋值给name,否则就会把默认值赋给name。

这类短路逻辑可以用来实现C和Java中的三元运算符(或条件运算符),Python2.5中有一个内置的条件表达式,a if b else c.如果b为真,则返回a,如果b为假,则返回c。这个运算符不需要引入临时变量,就可以直接使用,从而得到与input例子中相同的结果。

8.断言

一般来说,你可以要求某些条件必须为真(例如:在检查函数参数的属性时,或者作为初期测试和调试过程中的辅助条件),语句中使用的关键字是assert。

如果需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert语句就有用了,它可以在程序中置入检查点。条件后可以加字符串,用来解释断言。

>>> x=1
>>> assert 0<x<3
>>> assert 3<x<5
Traceback (most recent call last):
 File "<pyshell#12>", line 1, in <module>
 assert 3<x<5
AssertionError

>>> assert 3<x<5, 'wrong range'
Traceback (most recent call last):
 File "<pyshell#14>", line 1, in <module>
 assert 3<x<5, 'wrong range'
AssertionError: wrong range

>_ 循环

1.while循环

>>> x = 1 >>> while x<=100: print(x) x +=1 

打印1到100.

2.for循环

要为一个集合(序列和其他可迭代对象)的每个元素都执行一个代码块时,使用for循环可能比while循环更合适。

可迭代对象是指可以按次序迭代的对象,也就是用于for循环中的。

>>> words = ['1','2','3','4'] >>> for word in words: print(word) 1 2 3 4 

因为迭代(循环)某范围的数字是很常见的,所以有个内建的范围函数供使用:range()

range()方法包含下限,但是不包含上限,如果希望下限为0,可以只提供上限。

如果能使用for循环,尽量不要使用while循环。

在python3.0之前,range()函数一次创建整个序列,xrange()函数一次只创建一个数。当需要迭代一个巨大的序列时xrange()函数会更高效。在python3.0后,range被转换成xrange风格的函数。

3.循环遍历字典元素

第一种方法是遍历键,然后根据键获取对应的键值。第二种方法是使用items()函数将字典中的元素返回为元组,然后利用序列解包,得到key和value。

字典元素的顺序通常是没有定义的。也就是说,迭代的时候,字典中的键和值都能保证被处理,但是处理顺序不确定。如果顺序很重要的话,可以将键值保存在单独的列表中,例如在迭代前进行排序。

>>> d {'3': 3, '1': 1, '2': 2} >>> for key in d: print(key,'对应',d[key]) 3 对应 3 1 对应 1 2 对应 2 >>> for key,value in d.items(): print(key,'对应',value) 3 对应 3 1 对应 1 2 对应 2

4.迭代工具

(1)并行迭代:同时迭代两个序列

>>> names = ['ray', 'Joy', 'Sam', 'James']
>>> ages = ['22','22','21','19']
>>> for i in range(len(names)):
print(names[i],' is ',ages[i],' years old')
ray is 22 years old
Joy is 22 years old
Sam is 21 years old
James is 19 years old

内建的zip函数就可以用来进行并行迭代,可以把两个序列“压缩”在一起,然后返回一个元组的列表。

>>> for name,age in zip(names, ages):
print(name,' is ', age, ' years old')
ray is 22 years old
Joy is 22 years old
Sam is 21 years old
James is 19 years old

zip函数 可以作用于任意多的序列。zip可以处理不等长的序列,当最短的序列“用完”的时候就会停止。

>>> x = zip(range(5), xrange(100000))
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
x = zip(range(5), xrange(100000))
NameError: name 'xrange' is not defined
>>> x = zip(range(5), range(100000))
>>> x
<zip object at 0x037E3968>
>>> for y in x:
print(y)
(0, 0)
(1, 1)
(2, 2)
(3, 3)
(4, 4)

在Python3.5中range和xrange已经合并了。

(2)按索引迭代

enumerate函数可以在提供索引的地方迭代索引-值对。

>>> names
['ray', 'Joy', 'Sam', 'James']
>>> for index,value in enumerate(names):
if 'ray' in value:
names[index] = 'Ray'
>>> names
['Ray', 'Joy', 'Sam', 'James']

(3)翻转和排序迭代

reversed函数和sorted函数作用于任何序列或可迭代对象上,不是原地修改对象,而是返回翻转或排序后的版本。sorted函数返回列表,而reversed函数返回一个可迭代对象。不能直接对它进行索引、分片以及调用list方法,如果希望进行这些操作,可以使用list类型转换返回的对象。

>>> a
[1, 2, 3, 4]
>>> sorted(a)
[1, 2, 3, 4]
>>> sorted(a)[1:2]
[2]
>>> reversed(a)
<list_reverseiterator object at 0x037DCF10>
>>> list(reversed(a))
[4, 3, 2, 1]
>>> reversed(a)[1:2]
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module>
reversed(a)[1:2]
TypeError: 'list_reverseiterator' object is not subscriptable
>>> list(reversed(a))[1:2]
[3]

>_ 跳出循环

1. continue和break语句

continue是结束当前这个循环,进入下一次循环,整个循环并没有结束。break是跳出整个循环,执行别的代码。

2.while True/break


>>> while True:
word = input('Please input a word:')
if not word: break
print('the word is:', word)
Please input a word:a
the word is: a
Please input a word:b
the word is: b
Please input a word:

3.循环中的else子句:防止发生跳出循环却什么都没做的情况。

>>> from math import sqrt
>>> for n in range(99,81,-1):
root = sqrt(n)
if root == int(root):
print(n)
break
else:
print('Did not find it')
Did not find it
>>> for n in range(99,81,-1):
root = sqrt(n)
if root == int(root):
print(n)
break
else:
print('会执行很多遍')
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍
会执行很多遍 >>> for n in range(99,81,-1): root = sqrt(n) if root == int(root): print(n) else: print('Did not find it') Did not find it >>> for n in range(99,81,-1): root = sqrt(n) else: print('Did not find it') Did not find it

>>> for n in range(99,80,-1):

root = sqrt(n)

if root == int(root):

print(n)

break

else:

print('Did not find it')

81

>_ 列表推导式——轻量级循环

列表推导式是利用其它列表创建新列表的一种方法。

>>> girls = ['alice', 'bernice', 'clarice']
>>> boys = ['chris', 'arnold', 'bob']
>>> [b+'+'+g for b in boys for g in girls if b[0] == g[0]]
['chris+clarice', 'arnold+alice', 'bob+bernice'] >>> (b+'+'+g for b in boys for g in girls if b[0] == g[0]) <generator object <genexpr> at 0x037E8C00>

使用普通的圆括号而不是方括号不会得到“元组推导式”,在Python2.3及以前的版本中会得到错误,在最近的版本中,则会得到一个生成器。

上面男孩/女孩名字对的例子效率不高,因为它会检查每个可能的配对。Alex Martelli推荐的一个方法:构造一个叫做letterGirls的字典,其中每一项都把单字母作为键,以女孩名字组成的列表作为值。在字典建立后,列表推导式循环整个男孩集合,查找那些和当前名字首字母相同的女孩集合。这样列表推导式就不用尝试所有的男孩女孩的组合,检查首字母是否匹配。

>>> letterGirls = {}
>>> for girl in girls:
letterGirls.setdefault(girl[0], []).append(girl)
>>> letterGirls
{'c': ['clarice'], 'b': ['bernice'], 'a': ['alice']}
>>> print([b+'+'+g for b in boys for g in letterGirls[b[0]]])
['chris+clarice', 'arnold+alice', 'bob+bernice'

>_ pass、del和exec

1.pass语句可以做占位符使用

比如测试的时候有一个elif语句缺少代码块,在python中空代码块是非法的,那么将无法执行,这时,就可以用pass来取代这个空代码块。

>>> if x==1:
print(x)
elif x==2: #还没完...
pass
elif x==3:
print(3)

注释和pass语句联合的替代方案是插入字符串,对于那些没有完成的函数和类来说这个方法尤其有用,它们会扮演文档字符串的角色。

2.del删除

Python有自己的垃圾回收机制。

>>> x
1
>>> del x
>>> x
Traceback (most recent call last):
File "<pyshell#106>", line 1, in <module>
x
NameError: name 'x' is not defined

del语句不仅会移除一个对象的引用,也会移除那个名字本身。删除的只是名称,而不是列表本身(值)。事实上,在Python中是没有办法删除值的(也不需要过多考虑删除值的问题,因为在某个值不再使用的时候,Python解释器会负责内存的回收)。

3.exec

在Python3,0中,exec是一个函数而不是语句。

有些时候可能会需要动态地创造Python语句,然后将其作为语句执行或作为表达式计算,这时就需要exec函数。

如果程序将用户提供的一段内容中的一部分字符串作为代码执行,程序可能会失去对代码执行的控制,这种情况在网络应用程序——比如CGI脚本中尤其危险。

>>> exec('print("hello world")')
hello world

使用简单形式的exec绝不是好事,很多情况下可以给它提供命名空间(作用域,scope)——可以放置变量的地方。可以通过增加in<scope>来实现。其中的<scope>就是起到放置代码字符串命名空间作用的字典。

4.eval

是类似于exec的内建函数。exec会执行一系列的Python语句,而eval会计算Python表达式(以字符串形式书写),并返回其结果值。

>>> eval(input('a expression:'))
a expression:1+2
3

可以给eval语句提供两个命名空间,一个全局的一个局部的。全局的必须是字典,局部的可以是任何形式的映射。

尽管表达式一般不给变量重新复制,但它们的确可以(比如可以调用函数给全局变量重新赋值),所以使用eval语句对付一些不可信任的代码并不比exec语句安全。

>>> scope = {}
>>> scope['x'] = 2
>>> scope['y'] = 4
>>> eval('x*y', scope)
8


  0