欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python学习笔记_第五章:条件,循环和其他语句

程序员文章站 2022-06-15 18:42:26
...

Python3.0中,print不在是语句而是一个函数(功能基本不变)

赋值的魔法

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

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

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

可以交换两个变量的值(更多变量也是没问题的)

>>> scoundrel = {'name' : 'Robin', 'girlfriend' : 'Marion'}
>>> key, value = scoundrel.popitem()
>>> key, value
('girlfriend', 'Marion')
>>> print key, value
girlfriend Marion

当函数或方法返回元祖时,这个特性尤为重要,popitem方法将键-值对作为元祖返回,那么这个元祖可以直接赋值到两个变量中。
这里做的事事实上是序列解包,或递归解包。
Python3.0中有另外一个解包特性,可以像在函数参数列表中那样使用星号运算符

>>> a, b, *c = [1, 2, 3, 4]
>>> a, b, c
(1, 2, [3, 4])
>>> *a, b, c = [1, 2, 3, 4]
>>> a, b, c
([1, 2], 3, 4)

链式赋值

>>> x = y = 1
>>> x, y
(1, 1)

增量赋值

>>> fnord = 'foo'
>>> fnord += '**'
>>> fnord
'foo**'
>>> fnord *= 2
>>> fnord
'foo**foo**'

条件和条件语句

False None 0 "" () [] {} 作为布尔表达式时会被解释器看成是假
换句话说,也就是标准值False和None、所有类型的数字0(包括浮点型、长整型和其他类型)、空序列(比如空字符串、元祖、列表)以及空的字典都为假,其他的一切内建型都是真,但是我们可以自己构建可以被解释为真或假的对象。
bool函数可以用来转换其他值。

>>> bool('I think, therefore I am')
True
>>> bool(42)
True
>>> bool(0)

但是,所有值都可以用作布尔值,几乎不用对他们进行显式转换

流程控制

if else elif

更复杂的条件

1.比较运算符
x == y、x < yx > y、x >= y、x <= y、x != y、x is y、x is not y、x in y、x not in y
比较不兼容类型
Python3.0以前的版本是可行的,但是不应该这么做,因为执行结果不一定,Python3.0以后版本中,比较不兼容类型是违法的。
比较对象的时候可以使用内建函数cmp
有些运算符特别值得关注,后面开始介绍
1.is与==的区别
is是判断同一性,==是判断相等性
应避免将is运算符用于比较类似数值和字符串这类不可变值,由于Python内部操作这类对象的方式的原因,使用is运算符的结果是不可预测的。
2.字符串和序列比较
按照字母顺序排列进行比较

>>> ord('c')
99
>>> chr(99)
'c'

字符是按照本身的顺序值排列的,ord函数、chr函数的作用如上
3.布尔运算符
and、or、not
事实上,所有值都可以解释为布尔值,所有的表达式也都返回布尔值
短路逻辑
短路逻辑可以用来实现c和java中所谓的三元运算符(条件运算符:如表达式:()? a : b)Python2.5中有一个内置的条件表达式:
a if c else c

断言

关键字:assert
语法:assert (条件表达式),‘description’

>>> age = -1
>>> assert 0 < age < 100, 'age must be a number that bigger than 0 smaller than 100'

Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    assert 0 < age < 100, 'age must be a number that bigger than 0 smaller than 100'
AssertionError: age must be a number that bigger than 0 smaller than 100

for、while
如何防止输入为一个由空格组成的字符串
1.while not name or name.isspace()
提示重新输入name
2.while not name.strip()
提示重新输入name
如果能使用for循环,尽量不要使用while
xrange函数的循环行为类似于range函数,区别在于range函数一次创建整个序列,而xrange函数一次只创建一个数。当需要迭代一个巨大的序列时xrange会更高效,Python3.0中,range会转换为xrange风格的函数。

循环遍历字典元素

>>> d = {'x' : 1, 'y' : 2, 'z' : 3}
>>> for key in d:
    print key, 'corresponds to' , d[key]    
y corresponds to 2
x corresponds to 1
z corresponds to 3

仅仅需要一个for循环即可

>>> for key, value in d.items():
    print key, 'corresponds to', value  
y corresponds to 2
x corresponds to 1
z corresponds to 3
>>> 

Python2.2之前,只能用keys等字典方法来获取键,不能直接迭代字典,如果需要值用values方法代替keys方法,items方法返回键值对组成的元祖,for循环可以直接对其解包。

一些迭代工具

Python的迭代工具有些位于itertools模块儿中,还有一些内建的函数
1.并行迭代
使用内建的zip函数可以实现并行迭代,它的作用是压缩两个队列,然后返回一个元祖的列表

>>> names = ['zhangsan', 'lisi', 'wangwu']
>>> ages = ['17', '18', '19']
>>> for name, age in zip(names, ages):
    print name, age 
zhangsan 17
lisi 18
wangwu 19

zip函数也可以作用于任意多的序列,并且,可以处理不等长的序列,当最短序列用完时就会停止。
2.按索引迭代
按索引迭代一种有效的方法是使用内建的enumerate函数

>>> for index, name in enumerate(names):
    print index, name   
0 zhangsan
1 lisi
2 wangwu

3.翻转和排序迭代
sorted方法:返回排序后的序列,非原地排序
reversed方法:返回翻转后的序列,非原地翻转
sorted方法返回列表,而reversed方法返回一个奇怪的迭代对象,反正不是列表,但是可以放心地在join方法和for循环中使用,不过不能对它使用索引、分片以及调用list方法。

跳出循环

break, continue

循环中的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"

    
don't find it

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

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

>>> a = [x * x for x in range(10)]
>>> a
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

一般用法

>>> a = [x * x for x in range(10) if x % 3 == 0]
>>> a
[0, 9, 36, 81]

复杂一点的

>>> [(x, y) for x in range(3) for y in range(5)]
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4)]

包含多个for
注意使用普通圆括号代替方括号不会产生元祖推导式。Python2.3以前的版本中只会得到错误。而在最近的版本中会产生一个生成器

>>> grils = ['xiaomei', 'meina', 'linyu']
>>> boys = ['xiaoming', 'meiquan', 'longdong']
>>> letterGirls = {}
>>> for gril in grils:
    letterGirls.setdefault(gril[0], []).append(gril)

    
>>> print([b + '+' + g for b in boys for g in letterGirls[b[0]]])
['xiaoming+xiaomei', 'meiquan+meina', 'longdong+linyu']

字典的一个相关应用,上例中男孩名字的首字母集合应是女孩名字首字母集合的一个子集

三人行

什么都没有发生

pass

使用del删除

del不仅会移除一个对象的引用,也会移除名字本身,当两个名字同时引用同一个对象时用del删除name1后仍然可以通过name2访问到对象,原因是删除的仅仅是名字本身,而被引用的对象是不会被删除的,事实上,Python中没有办法删除值。

用exec和eval执行 和 求和某字符串

tip:CGI脚本:web服务器运行时外部程序的规范,按CGI编写的程序可以扩展服务器的功能。
1.exec:执行一个字符串的语句是exec,在Python3.0中,exec是一个函数而不是一个语句

>>> exec "print 'hello world!'"
hello world!

exec最大意义在于动态创建代码字符串来修改程序,但这样做很不安全,可以通过增加一个字典,起到命名空间的作用。
可以通过增加in <scope>来实现,其中<scope>是可以起到放置代码字符串字符空间作用的字典

>>> from math import sqrt
>>> scope = {}
>>> exec 'sqrt = 1' in scope
>>> sqrt(4)
2.0
>>> scope['sqrt']
1
>>> len(scope)
2
>>> scope.keys()
['__builtins__', 'sqrt']

这种方式创建的字典中会自动加入一个‘builtins’键,可以索引到所有的内建函数
2.eval:一个内建函数,eval会计算Python表达式,并返回结果

>>> exec '6 + 18 * 2'
>>> 6 + 18 * 2
42
>>> eval('6 + 18 * 2')
42

Python3.0中row_input()被重命名为input()
根exec一样,eval也可以使用命名空间,尽管表达式几乎不像语句那样为变量重新赋值。这里可以给eval提供全局和局部两个命名空间,全局命名空间必须是字典,局部命名空间可以是任意形式的映射。
表达式一般不给变量重新赋值,但是某些情况下的确可以(比如可以调用函数给全局变量重新赋值)。所以对于不安全的的代码eval并不比exec安全。目前Python中没有任何执行不可信任代码的方式。一个可选方案是使用Python的实现,比如Jython,以及用一些本地机制,比如Java的sandbox功能。
初探作用域
给exec或者eval语句提供命名空间时,还可以在真正使用命名空间前放置一些值进去:

>>> scope = {}
>>> scope['x'] = 2
>>> scope['y'] = 3
>>> len(scope)
2
>>> eval('x * y', scope)
6
>>> len(scope)
3

同理,exec或eval调用的作用域也能在另一个上使用

>>> scope = {}
>>> exec 'x = 2' in scope
>>> eval ('x * x', scope)
4