一、python控制结构
Python通过if语句实现条件分支,通过while语句与for...in语句实现了循环。
Python中还有一种条件表达式——这是一种if语句,也是Python对C风格语言中使用的三元算子(?:)相对应的内容。
1、条件分支
条件分支语句最通常的语法:
可以有0个或多个elif语句,最后一个elif语句是可选的。如果需要考虑某个特定情况,但在该情况出现时又不需要做什么,那么可以使用pass(充当“什么也不做”占位符)作为该分支的suite。有些情况下,可以将一条if...else语句缩减为单一的条件表达式,其语法如下:
expression1 if boolean_expression else expression2
如果boolean_expression为True,条件表达式的结果为expression1,否则为expression2。例如:
width = 100 + (10 if margin else 0)
如果margin为True,则width为110,否则为100,注意如果没有括号,则为0,因为此时Python将100+10作为expression1,因此使用圆括号的法则跟C语言类似。
条件分支可用于提供为用户打印的消息,比如,在报告处理的文件数量时,不再打印“0 file(s)”、“1 file(s)”,而是使用一对条件表达式:
上面的语句将打印“no files”、“1 file”、“2 files”,并且同时会留下一个更专业的印象。
2、循环
1)while循环
while循环完整的语法如下:
else分支是可选的,只要boolean_expression为True,while块的suite就会执行,如果boolean_expression为False,循环终止,此时,如果存在可选的else分支,就会执行其suite。在while块的suite内部,如果执行了continue语句,就会跳转到循环起始处,并对boolean_expression的取值进行重新评估。只要循环是正常终止的,else分支的suite就总会执行。如果由于break语句、或由于返回语句(如果循环在函数或方法内)、或由于发生异常导致跳出循环,else分支的suite就不会执行。发生异常时,Python会跳过else分支并寻找适当的异常处理部分。此外,else分支的这些特点对while循环、for...in循环以及try...except块都是一样的。
2)for循环
for循环完整的语法如下:
通常,expression或者是一个单独的变量,或者是一个变量序列,一般是以元组形式给出的。如果将元组或列表用于expression,则其中的每一数据项都会拆分到表达式的项。
如果在for...in循环suite中执行了continue语句,那么控制流立即跳转到循环起始处,并开始下一次迭代。如果循环正常执行完毕,就会终止循环,之后执行else suite。如果循环被跳出(由于执行了break语句或return语句),控制流会立即跳转到循环后的语句——所有可选的else suite将被跳过。同样地,如果发生异常,Python会跳过else分支并寻找适当的异常处理程序。
二、异常处理
1、捕获与产生异常
异常的捕获石使用try...except块实现的,其通常语法格式如下:
其中至少要包含一个except块,但else与finally块都是可选的。在try块的suite正常执行完毕时,会执行else块的suite——如果发生异常,就不会执行。如果存在一个finally块,则最后总会执行。每个except分支的异常组可以是一个单独的异常,也可以是包含在括号中的异常元组。对每个异常组,as variable部分是可选的。如果使用,该变量就会包含发生的异常,并可以在异常块的suite中进行存取。
如果某个异常发生在try块的suite中,那么每个except分支会顺序尝试执行。如果该异常与某个遗产组匹配,则相应的suite得以执行。要与异常组进行匹配,异常必须与组中列出的异常类型(或其中的某一个)一致,或者与组中列出的异常类型(或其中的某一个)的子类一致。如果没有哪个except块匹配该异常,Python会沿着调用栈回溯,并寻找适当的异常处理程序。如果找不到合适的异常处理程序,程序将终止,并在控制台上打印该异常以及回溯信息。
Python还提供了更简单的try...finally块,有时也是有用的:
不管try块的suite中发生什么,finally块的suite都将得以执行。
try...except...finally块的一种常见应用是处理文件错误。
异常提供了一种改变控制流的有用方法。我们可以使用内置的异常,或创建自己的异常,以便产生我们所需要的异常并对其进行处理。有两种可以产生异常的语法:
使用第一种语法时,指定的异常应该或者是内置的异常,或者继承自Exception的自定义异常。如果给定一些文本作为该异常的参数,那么在捕捉到该异常并打印时,这些文本应该为输出信息。使用第二种语法,也就是没有执行异常时,raise将重新产生当前活跃的异常——如果当前没有,就会产生一个TypeError。
2、自定义异常
自定义异常是自定义的数据类型(类)。创建自定义异常的基本语法如下:
class exceptionName(baseException): pass
基类应该为Exception类或继承自Exception的类。自定义异常的一个用途是跳出深层嵌套的循环。
三、自定义函数
函数可用于将相关功能打包并参数化。在Python中,可以创建4种函数:全局函数、局部函数、lambda函数、方法。
局部函数(也称为嵌套函数)定义在其它函数之内,本地函数只对对其进行定义的函数是可见的。
Lambda函数是表达式,因此可以在需要使用的地方创建,不过,这类函数要比通常的函数受更多的限制。
方法是与特定数据类型关联的函数,并且只能与数据类型关联在一起使用。
创建一个全局函数或局部函数的通用语法格式如下:
其中,parameters是可选的,如果有多于一个参数,就可以写成逗号分隔的标识符序列,或identifier=value对序列,比如:
在该函数内部,每个参数a,b与c都会使用传递的相应参数值进行初始化。调用该函数时,必须提供全部的参数值,比如,heron(3, 4, 5)。如果提供的参数值不足或过多,就会产生一个TypeError异常。
Python中的每个函数都有一个返回值,尽管忽略返回值是完全可以的。返回值可以是单独的一个值,也可以是一组值,还可以是组合类型的值,因此对于返回值的类型实际上没有限制。如果return不带参数,或者根本就没有使用return语句,那么函数将返回None。
使用parameter=default语法可以为参数指定默认值,需要注意的是,参数语法不允许在没有默认值的参数后面跟随默认值,因此,def bad(a, b=1, c):不能生效。另一方面,在传递参数时,并不是必须严格按照函数定义时的参数顺序——可以使用关键字参数,以name=value的形式进行参数传递。
1、名称与Docstrings
通常使用docstring,可以未任何函数添加文档信息,docstrings可以是简单地添加在def行之后、函数代码之前的字符串。对于函数文档而言,常规做法是docstring的第一行只是一个简短描述,之后是一个空白行,再之后跟随的就是完整的描述信息,如果是交互式输入再执行的程序,还会给出一些实例。
2、参数与参数拆分
我们可以使用序列拆分操作符(*)来提供位置参数。比如,如果需要计算某个三角形的面积,并且各个边的长度存放在一个列表中,就可以进行类似于如下的调用:heron(sides[0], sides[1], sides[2]),或简单地对列表进行拆分,并使用更简单的调用方式heron(*sides)。如果列表(或其它序列)包含比函数参数更多的项数,就可以使用分片提取出合适的参数。
就像我们可以对序列进行拆分来产生函数的位置参数一样,我们也可以使用映射拆分操作符(**)来对映射进行拆分。
3、存取全局范围的变量
如果不使用global语句,Python将变量视为局部变量,如果使用则会在全局范围内搜索该变量。
4、Lambda函数
Lambda函数使用如下语法格式创建:
lambda parameters: expression
parameters是可选的,如果提供,通常是逗号分隔的变量名形式,也就是位置参数,当然,def语句支持的完整参数语法格式也可以使用。expression不能包含分支或循环(但允许使用条件表达式),也不能包含return(或yield)语句,lambda表达式的结果是一个匿名函数。调用lanbda函数时,返回的结果是对表达式计算产生的结果。如果expression是一个元组,就应该使用圆括号将其包含起来。
下面给出一个简单的lambda函数,其作用是根据参数是否为1决定是否添加s:
s = lambda x:"" if x == 1 else "s"
lambda表达式会返回一个匿名函数,我们将该函数赋值给变量s。
任何(可调用的)变量都可以使用圆括号进行调用,因此,给定某一操作处理的文件数,可以使用函数s()输出一条消息,类似如下的方式:
print("{0} file{1} processed".format(count, s(count))).
5、断言
前提与后果可以使用assert语句指定,其语法格式如下:
assert boolean_expression, optional_expression
如果boolean_expression评价为False,就产生一个AssertionError异常。如果给定了可选的optional_expression,就将其用作AssertionError异常的参数——对提供错误消息而言,这种做法是有用的。需要注意的是,断言是为开发者设计的,而不是面向终端用户的。通常程序使用中发生的问题(如丢失文件或无效的命令行参数)应该采用其它途径处理,比如提供错误或日志消息。
在程序就绪并可以公开发布之后,应该怎样处理assert语句?我们可以通告Python不执行assert语句——在效果上,就是在运行时摒弃这些语句。这可以通过在运行程序时在命令行中指定-O选项来实现,比如,python -O program.py。另一种方法是将环境变量PYTHONOPTIMIZE设置为-O。
如果docstrings对用户没用,就可以使用-OO选项,其效果是摒弃assert语句与docstrings:注意没有哪个环境变量用于设置这一选项。有些开发者采用一种简单的方法:产生程序的一个副本,其中所有assert语句被注释掉,如果可以通过测试,就发布这个注释了assert语句的版本。