5.条件,循环和其他语句

5.1print和import的更多特性。

5.1.1使用逗号输出

print可以通过逗号输出多个表达式。

5.1.2把某件事作为另一件事导入

四种import的方式:

1.import module

2.from module import function1

3.from module import function1, function2...

4 from module import *:import module中的所有function

假如import两个module有名字相同的函数,那么可以直接用第一种方法区分。用法是module1.function()和module2.function()

也可以通过as为整个模块或者函数提供别名:

1.为模块提供别名

2.为函数提供别名

5.2赋值

5.2.1并行赋值:序列解包(sequence unpacking)

一般的赋值都是一个值赋值给一个变量,例如a=1。并行赋值则是多个不同的值赋值给多个变量。它的过程相当于把左边的所有变量和右边所有的值当成序列(等号右边可以是序列),把右边的序列解开,再把其中的值赋值到左边的每个变量上。这个过程也被称为序列解包。因为它是将左边变量和右边的值一一对应的过程,所以左右两边的变量数和值的数量必须相等(没有‘*’号时,下面会具体讲),否则会报错。

当然也可以在右边的值两旁添加'[ ]'直接转为序列:

当函数返回序列是,序列解包很容易快速获得序列中想要的数据。

另外,在序列解包中有时可以运用‘*‘号。例子如下:

没有星号的,根据他们的相对位置会被赋一个值(a是第一个,赋值1,c是最后一个,赋值4,剩下的全赋值给b),剩下的值都将以列表的形式赋值给有星号的变量。每一次并行赋值中最多只能有一个有星号的变量。

5.2.2链式赋值(chained assignment)

链式赋值就是一个值赋值给多个变量。变量间用等号连接。

c='a'
b=c
a=b

效果一样。

5.2.3增量赋值

简单来说,就是讲x=x+1这种式子用x+=1来表达。可以让代码显得更加简练和紧凑,但实质上并无差别。

有意思的是'*=’。经过前几章的学习,我们知道序列可以通过*来制造一个重复多次的序列。例如:

因为a*2是产生一个新的列表,所以重新赋值给a会改变a的地址。但是如果a*=2的话,虽然得出来的值一样,但是是会在原对象的基础上改变,所以地址没变。

但是如果序列是immutable(不可变的),像元组,是不能在原对象的基础上进行任何改变的,所以一定会创建新的元组,因此地址会改变。

5.3语句块

语句块是在条件为真(条件语句)时执行和执行多次(循环语句)的一组语句,需要在在代码前放置空格(python为四个)来缩进语句。

tab和空格的区别:tab和空格键都可以缩进。以python为例,在ide中设置tab缩进为四个空格长度后,两者表现是一样的,但是在其他人的ide中,如果设置tab为其他数量(例如x)的空格,那么tab键表现出来的缩进则是x格空格,而不再是4个。所以标准推荐方法是直接用空格而不是tab,那么在任何情况下缩进都会是4个空格。

另外,python对于缩进的要求很严格。像在java和c语言中,缩进更多的是为了程序的易读性,对程序的运行并不会有任何的影响,而在python中,错误的缩进会直接导致错误的运行,甚至报错。

在python中,是用冒号(:)用来标识语句块的开始。更多的语句块的例子可以在下面的条件语句和循环语句中找到。

5.4条件和条件语句

5.4.1布尔变量(boolean)

布尔变量有两个标准值,“True”和“False”(真和假),True==1, False==0。。下列的式子,作为布尔表达式时,会被解释器当成假:

False, None, 0, "", (), {}

除了这几个以外,其他的都会被解释器当成真。

请注意,有些函数返回值为0并不一定代表是返回False。例如Java中的String的compareTo函数,返回值的正负值代表比较的两个变量的大小关系,只有当返回值为0是才代表两个变量相等。

5.4.2条件执行和if语句

如果之前有其他语言的编程基础的话就很容易理解下面的部分。if后面的括号内就是条件,如果条件结果为True,就运行下面代码块的内容。如果结果为False,则直接跳过这一部分。

a=1
b=1
if (a==b):
    print('a equals to b')

结果:

可以添加else字句。如果if后面的条件结果为False,就运行else后面的代码块:

a=1
b=2
if (a==b):
    print('a equals to b')
else:
    print('a does not equal to b')

结果为:

如果需要检查多个条件,则可以添加elif(相当于其他语言的else if)字句:

a=1
b=2
if (a>1):
    print('a is greater than 1')
elif (b>1):
    print('b is greater than 1')
elif (a<b):
    print('a is smaller than 1')
else:
    print('None of the conditions has been met')

结果为:

代码的运行顺序是从第一个condition开始检查,因为(a<1)返回False(a等于一而不是小于1),所以跳过代码块直接检查第二个条件。因为b=2,所以(b>1)返回True,运行后面的代码块。运行完之后将直接跳过if-block后面的代码。所以,虽然第三个条件(a<b)返回True,但因为第二个条件已经已经满足了,后面的代码就不会被运行了,'a is smaller than 1'就不会被打印出来。

5.4.3if的嵌套

if的嵌套就是在if语句里面再加上新的if语句,并不难理解。主要是注意下在新的if语句中,需要再一次的缩进。避免犯出下面的错误。

a=2
b=1
if (a>1):
    print('a is greater than 1')
    if (b==2):
        print('Both conditions are met. Position 1')
    print('Both conditions are met. Position 2')

很明显,代码的本意是满足(a>1)的条件,打印'a is greater than 1‘,两个条件都满足时,打印'both conditions are met'。最后两句输出语句的区别在于一个缩进4个空格,一个缩进8个空格。既满足a>1又满足b==2会打印Position 1(缩进8格)的语句,而不是Position 2(缩进4格)。结果是:

因为b==2返回False,不应该打印出‘Both conditions are met’。所以Position2并不在嵌套里的if里面,而是在最外层的if中。正确的代码应该是:

a=2
b=1
if (a>1):
    print('a is greater than 1')
    if (b==2):
        print('Both conditions are met.')

结果就只有:

5.4.4更复杂的条件

各类运算符:

1.比较运算符:

简单来说,就是比较x,y的大小关系。只有当x,y类型一样或者接近时,比较才有意义。比较1000和‘zyx’的大小是毫无意义的。

2.相等运算符(==):

比较两个变量的值是否相等。

3.同一性运算符(is, is not):

判断x,y是否是指向同一个物体。例如:

(对于每项比较返回的布尔值的解释可以参考上一章字典的软复制(soft copy)部分。)

4.成员资格运算符(in, not in):

检查元素是否存在于某个变量中。例子可以参考上一章字典的key in dict。

5.字符串和序列比较

像上面的例子,一般来说,字符串和序列的比较是从第一个元素开始比较,相等的话再开始比较下一个元素,一直到其中一个字符串或序列结束或者两个元素不一样。需要注意的是在字符串的比较中,要注意下大小写的问题。一般来收都是先处理成都是大写或者小写再比较。而在序列的比较中,每个位置的元素类型最好一样。比如:

 

这个序列的比较看似是没有问题的,没有报错,而且能返回一个True。但是可以看到左边的序列第二个元素是int,而右边的序列第二个元素是一个序列[1,1]。如果需要比较到第二个元素的话,就会报错。

6.布尔运算值(and, or, not)

not就是negate,将True变成False,False变成True。

and(和):两边值都为True时,返回True,否则返回False。

or(或):只要有一边的值为True时,返回True,否则返回False。

可以用and,or来连接多个条件。not用来修饰条件。

需要注意的是,像and,是需要两边条件都为True时,才返回True,所以当计算第一个条件为False时,并不会再计算第二个条件,而是直接返回False。类似的对于or,如果第一个条件为True,那么将直接返回True,也不会再计算第二个条件。(short-circuit logic/ lazy evaluation)因此在条件中放入一些运算时需要多斟酌一下。

从上面的例子可以看到,由于是以0为除数,所以3/0的运行是会报错的。但是在and和or中,因为第一个条件是False和True,所以会跳过第二个条件,直接返回布尔值,3/0并不会报错。(因为根本没被运行,而3/0的错误是runtime error)

5.4.5断言

assert对于程序的测试是很有帮助的。他的功能是当assert的条件不被满足时,直接程序报错退出。很多时候是用来写test case。可以在assert的条件后面加‘,’再加string用来说明为什么出错。下面这个例子就是在除数为0时报错并说明理由。

5.5循环

循环就是一直重复某段代码直到某个条件不再被满足。

5.5.1while循环

用法(Pseudo-code):

while condition:
    do something

while循环中的代码块就会一直运行下去,直到condition不再被满足。

5.5.2for循环

在其他很多语言中,for的用法是类似于下面:

for (int a=0; a<10; a++)

这样代码块会运行十次。

而在python中,for是搭配in一起用。如果是遍历序列或者字典的话,可以直接用for变量in序列/字典。

序列:

字典:

如果要像其他语言一样迭代某范围的数字,可以用内建函数range:

range函数的两个参数代表着初始(包括)和结束(不包括)的index。上面的例子相当于其他语言的:

for (int a=0; a<10; a++){
  print('Run' + a + 'Times')
}

5.5.3一些迭代工具

1.并行迭代(zip)

 zip的功能就是将两个序列压缩成一个列表,然后返回那个列表的迭代器(zip object,python 3)。由于返回的是迭代器,所以并不能用index来获取element。迭代器可以理解为遍历一个容器(字典,序列等)的一个接口,更多的解释和例子会在第九章中提到。

例子如下:

2.编号迭代(enumerate)

enumerate在迭代式会同时返回索引和数据。

3.翻转(reversed)和排序迭代(sorted)

功能同列表中的reverse和sort类似,但是是作用于可迭代对象上,而不是原地修改对象。

需要注意的是sorted是直接返回一个列表,但是reversed是返回一个迭代器。

5.5.4跳出循环

break和continue:在迭代时,有时并不一定循环到结尾。例如,检查一个数组中是否含有数字1,从第一个元素开始检查,如果检测到了1,就可以直接退出迭代,而不用继续检查其他元素。像这种情况,则需要利用break或者continue来跳出循环。

break和continue区别:break是跳出循环,而continue是跳过当前循环的剩下部分,直接开始下一循环。在其他语言中的switch-case语句中经常用到。

需要注意的时,如果在循环里面嵌套循环,即使break是在里循环中,一旦运行到break,仍然是会跳出外循环。

5.6列表推导式(list comprehension)--轻量级循环

简单来说,就是利用已有的列表创建新列表。像下面的例子,就是将range(10)这个列表的每个元素求平方,再存到另一个列表中。

可以和更多的for和if语句一起用

在上面的例子中,x和y的所有元素都会组合成一对,不满足if条件的会在结果中去除。

5.7pass,del和exec&eval

pass:pass就是一个什么都不运行的语句。因为在python中,空代码块是不被允许的,如果暂时不知道在if或者其他需要代码块的语句需要填什么的话,可以先填写pass。

del:我们都知道,变量实际是对对象的引用,在赋值给一个变量之后又赋其他值给同一个变量,只是让变量成为另一个对象的引用。del的功能则是完全删除变量对对象的引用,以及移除名字本身。例如del x之后,再次引用x则会显示undefined(未定义)。

exec:执行字符串中的python语句,并不返回任何对象:

eval:计算python表达式,返回结果值:

从string或者code对象中执行代码也是python作为动态语言的一个特色。可以应用在服务器的热部署方面,除非大的版本更新,可以只重新部署改动的部分,而不是所有代码。exec和eval更多的实际操作可以等到有具体需求时再去了解。exec的原理可以参考下面的文章:

http://lucumr.pocoo.org/2011/2/1/exec-in-python/

猜你喜欢

转载自www.cnblogs.com/tanfengji/p/9217534.html