吃透Python-第 2 章 打印输出和键盘输入
本章,我会通过执行打印输出和读取键盘输入的程序,带领大家学习各项内容。
脚本程序
脚本文件和扩展名 .py
评论(注释)
空行
表达式和语句
函数
内置函数
函数调用/调用运算符/实参
使用 print 函数执行打印输出操作
向 print 函数传递 end 参数和 sep 参数
使用 input 函数读取键盘输入
使用 int 函数将字符串转换为整数
使用 float 函数将字符串转换为浮点数
使用 str 函数将数值转换为字符串
使用 bin 函数 /oct 函数 /hex 函数将整数转换为字符串
使用 format 方法格式化字符串
幻数
用变量存储常量
程序编码的指定与 UTF-8
2-1 打印输出
上一章我们利用交互式 shell 学习了 Python 的基础内容。从本章开始,我们将执行保存为文件的 Python 程序。
使用 print 函数执行打印输出操作
我们来思考一下使用任意一个数值(而非决定好的数值)进行计算的情况。
如下图所示,读取两个整数并输出它们的和。输入的值不同,计算出的结果也不同。
虽然我们也能在交互式 shell 中逐行输入该代码,并以会话形式执行该程序,但每次执行时都需要重新输入程序代码。
脚本程序
大家在使用 Word 办公软件和编辑器编写好文章后,一般会对其进行保存。文章保存之后可以随时被修改和打印。程序也是如此,一旦被保存为文件后,就可以随时修改和执行。
这样的程序称为脚本程序(script program),存储脚本程序的文件称为脚本文件(script file)。
我先从代码清单 2-1 开始讲解。这是一个在屏幕上显示“Hello!”的程序。
▶ 附录 A-2 节总结了保存和执行程序的方法。在集成开发环境 IDLE 中输入或读取程序代码后,只要按 F5 键就能执行程序。
注释
我们先来看程序的第一行。# 表示的含义如下。
该行中 # 之后的内容是向阅读程序的人传达的信息。
也就是对程序的评论(comment),亦称注释。
不论有无注释,以及注释的内容是什么,程序的执行都不会受到影响。注释中可以用中文或英语简明扼要地记录要向阅读程序的人(包括程序开发者自己)传达的信息。
▶ # 之后一般会插入一个空格(# 不是升音符)。
另外,'ABC#DEF'这种字符串字面量中的 # 不会被识别为注释的开始符号。
要点 脚本程序中会简明扼要地记录注释,以便包含程序开发者在内的读者阅读。
如果他人编写的程序中附带了合适的注释,代码就会变得易于阅读和理解。另外,程序开发者不可能永远记得开发思路,因此编写注释对开发者自己来说也非常重要。
空行
第二行是空行(blank line),空行对程序的运行没有影响。在代码之间的适当位置插入空行,能避免代码扎堆,使代码更容易阅读。
使用 print 函数打印输出
实际上,从零开始编写一个能够执行打印输出操作的程序极其困难,所以一般会使用名为 print 的函数。
函数像是一种专门执行处理的零件。在使用它之前,需要进行函数调用(function call)。
如图 2-1 所示,调用 print 函数相当于将操作交给 print 函数处理,() 中传递的实参(argument)起辅助指示的作用。解释得更形象一些,这个过程就像下面这样。
print 函数先生,字符串 'Hello!' 已经给您,请把它显示出来。
另外,包围实参的 () 称为调用运算符(call operator)。
print 函数被调用后会将传递过来的字符串和换行符显示在屏幕上。
▶ 只输出字符串本身,不输出单引号 '。
图 2-1 使用 print 函数打印输出
另外,像 print 函数这种默认可以使用的函数称为内置函数(built-in function)。Python 中也有非内置函数的概念。
代码清单 2-1 中除去注释和空行,实际上只有一行代码。调用和执行 print 函数后,程序结束运行。
▶ 我会在后面的内容中逐步讲解函数相关的概念。
打印输出和换行
下面来打印输出“你好。”和“初次见面。”。具体请见代码清单 2-2。该程序按顺序调用 print 函数,打印输出字符串并换行。
打印输出时不换行的方法
有时,我们希望程序在打印输出时不执行换行操作(自动换行会引发问题)。代码清单 2-3 就是在不换行的情况下执行打印输出操作的程序示例。
在给函数传递多个实参时要像该程序这样用逗号将各个实参隔开。另外,传递给 print 函数的第二个实参 end=‘’ 的含义如下。
在打印输出的过程中换行的方法
如果要在打印输出的过程中进行换行,就要把换行符 \n(第 13 页)插入字符串字面量中。代码清单 2-4 和代码清单 2-5 显示了相同的内容。
只进行换行
如果只想换行,可以调用 print 函数并在 () 内留空。也就是说,在不传递实参的情况下调用 print 函数可以输出换行符。
我们来看一下代码清单 2-6。
print 函数调用既可以理解为表达式,又可以理解为语句。程序内的各个语句一般按照先后顺序执行。
▶ 第 1 章介绍过表达式和语句的相关内容,下一章我们会进一步学习。
字符串字面量的求值与 print 函数
在第 1 章中,我们通过在交互式 shell 中输入字符串字面量来打印输出字符串的值。这种打印输出方式与使用 print 函数的方式完全不同。
我们先看一下使用交互式 shell 的方式。首先是字符串字面量(例 2-1)。
因为字符串字面量 ‘Hello\nGood Bye!’ 是一种表达式,所以对其求值后得到的值(字符串本身)会返回给交互式 shell,由交互式 shell 打印输出该值。
交互式 shell 只打印输出字符串本身。因为换行符显示为 \n,所以这种输出方式面向的是计算机而不是人。
▶ 我将在下一章详细讲解“求值”。
下面调用 print 函数(例 2-2)。
调用 print 函数并传递字符串字面量 ‘Hello\nGood Bye!’ 作为实参。
执行 print 函数后程序打印输出了“Hello!”和“Good Bye!”。这次没有显示 \n,而是进行了实际的换行。这种输出方式以人为对象。
▶ 表达式解释为语句的相关内容会在 3-1 节介绍。
2-2 读取键盘输入
上一节我们编写了打印输出的程序,本节我们将编写能读取键盘输入并以会话方式运行的程序。
使用 input 函数读取通过键盘输入的字符串
首先,我们来读取通过键盘输入的内容(图 2-2)。代码清单 2-7 是先询问名字,再将其作为字符串读取和显示的程序。
图 2-2 读取通过键盘输入的字符串
首次出现的 input 函数在读取通过键盘输入的字符串后会将该字符串返回。第 9 章会介绍函数的返回值,现在我们只要理解表达式 input() 会变成从键盘输入的字符串即可。
在运行示例中,表达式 input() 会变成读取的字符串 ’ 福冈太郎 ',该字符串又会赋给变量 name。
第 1 章提到过,变量在赋值时会被声明并自动确定类型。变量 name 的类型是字符串型(str 型),它的值是 ‘福冈太郎’。
我们也可以通过以下传递实参的形式调用 input 函数。
input(' 显示的字符串 ')
使用这种调用方式时,程序会在屏幕上输出显示的字符串(此时不输出换行符),然后读取字符串。
代码清单 2-8 就是按照这种方式改写的程序。
两行代码汇总成一行后,程序变得更加简洁。
在运行示例中,表达式 input(’ 你的名字是:') 的值变成读取的字符串 ’ 福冈太郎 ',赋给了变量 name。
▶ input 函数虽然会读取到回车键(相当于换行符)为止的输入,但返回的字符串末尾不包含换行符。
打印输出多个字符串
请注意看前面两个示例程序的最后一行。传递给 print 函数的实参有三个,分别是 ‘你好’、name 和 ‘。’。像这样,给 print 函数传递用逗号隔开的多个实参后,程序会从左至右依次输出这些参数。
这里需要注意的是,print 函数在接收并打印输出多个字符串时,会在各字符串之间用空格作为分隔符。
代码清单 2-9 所示的程序则没有输出空格作为分隔符。
传递给 print 函数的最后一个实参 sep=‘’ 表示的含义如下。
▶ sep 可以指定为任意字符串。如果设定 sep='\n',则程序每打印输出一个实参后会换行;如果设定 sep='---',则程序会输出“你好 --- 福冈太郎 ---。”,即各部分被 --- 隔开。
使用 + 拼接和输出字符串时不会显示空格。我们来看一下代码清单 2-10。
字符串转换为数值
下面,我们来编写读取两个整数并对其进行加减乘除运算,最后输出运算结果的程序。请看代码清单 2-11。
▶ 除了加减乘除运算,这里还进行了求幂运算并输出了结果。此外,如果变量 b 的值为 0,除数就为 0,进行除法运算会导致错误发生。第 3 章和第 12 章会讲解此类情况的处理办法。
在运行示例中,读取的字符串 ‘7’ 赋给了变量 s。虽然 str 型字符串 ‘7’ 由数值构成,但它并不是数值(int 型或 float 型的值)。
这里需要使用将字符串转换为 int 型整数的 int 函数。如图 2-3 所示,调用 int( 字符串 ) 后,字符串转换为整数,该整数被返回。
另外,表示二进制整数、八进制整数和十六进制整数的字符串通过 int( 字符串 , 基数 ) 进行转换。在将字符串转换为 float 型实数时使用 float( 字符串 ) 调用 float 函数。
▶ 在调用表达式执行转换操作时,如果传递的字符串不能转换为数值,就会产生错误,如 int('H2O') 和 float('5X.2')。
图 2-3 字符串转换为数值
如果将字符串的读取操作和数值的转换操作合并,代码会更加简洁。请看代码清单 2-12。
此处仅显示代码的变更部分,以后也会省略相同部分的代码。
执行该程序并输入与前面运行示例相同的值后,int(‘7’) 的返回值 7 会赋给 a,int(‘3’) 的返回值 3 会赋给 b。
另外,在输出运算结果时,由于未指定用于分隔的字符串 sep,所以各部分之间(即运算结果的数值前后)会显示空格。
但是,如果仿照代码清单 2-10 编写如下程序,程序就会产生错误。
print('a + b 等于' + a + b + '。') # 错误
就像第 1 章讲解的那样,字符串和数值不能用 + 拼接。
将数值转换为字符串后进行拼接可以避免发生错误。图 2-4 所示的 str 函数可以将数值转换为字符串,即进行 int 函数和 float 函数的逆转换。
图 2-4 将数值转换为字符串
如图所示,将数值转换为表示二进制数的字符串、表示八进制数的字符串和表示十六进制数的字符串时,使用的分别是 bin 函数、oct 函数和 hex 函数。
我们使用 str 函数改写程序代码。具体如代码清单 2-13 所示。
▶ 后面会介绍如何在字符串中插入数值。
使用 format 方法格式化字符串
我们已经知道,由于字符串和整数不能拼接,所以处理起来很麻烦。实际上,有办法可以在字符串中插入整数。
先来执行一下代码清单 2-14 的这个程序。
对比程序和运行示例后,即使不理解代码的准确含义,大家应该也能猜到程序在做什么。
该程序使用以下形式的表达式执行打印输出。
字符串.format(并列的实参) ※字符串中包含 {}。
这是一个先将 format 后面的 () 中的实参转换为字符串,再将其插入 {} 并生成新的字符串的表达式(当存在多个实参时,实参按从前往后的顺序插入 {})。
图 2-5 显示了运行示例中向字符串插入数值的过程。插入数值后生成的新的字符串,会传递给 print 函数并显示出来。
图 2-5 在字符串中插入数值
我们试着使用 format 方法改写前面的程序。代码清单 2-15 就是代码清单 2-9 改写后的程序。
在这个程序中,使用 format 插入的是字符串而不是数值。
下面改写代码清单 2-13,改写后的程序如代码清单 2-16 所示。
format 不仅能执行插入操作,还能执行各种格式化操作,包括居左、居中、居右和指定位数等。
要点 我们可以使用字符串 .format(...) 这种形式,在字符串中插入(格式化的)其他字符串或数值,以生成新的字符串。
print 是函数,而 format 是方法。函数与方法有许多共同点,比如在调用时都会在末尾加上 (),不过二者也有许多不同点。
我会在第 6 章和第 11 章详细讲解方法。
这里我们只学习如何使用 format 方法进行格式化。格式化的方法还包括使用运算符 % 和使用 f 字符串。我们会在第 6 章学习具体内容。
用变量表示常量
现在,我们来编写一个读取从键盘输入的圆的半径,计算圆的周长和面积并显示结果的程序。程序如代码清单 2-17 所示。
▶ 这里使用 float 函数将字符串转换为浮点数(实数)。
该程序根据公式计算圆的周长和面积(半径为 r 的圆,其周长为 2πr,面积为 πr2)。
这里,圆周率 π 为 3.14,但 π 的值并不等于 3.14,而是无限小数 3.1415926535…。
如果想更精确地计算圆的周长和面积,可以将圆周率的值,即蓝色底纹部分改为 3.14159。
该程序只涉及两处改动,但在大规模的数值计算程序中,π 出现的地方可能有几百处。
使用编辑器的替换功能可以轻易将所有的 3.14 替换为 3.14159,但是代码中的某些 3.14 表示的并不是圆周率,而是其他值。在替换过程中,我们势必要将这些 3.14 排除,也就是要有选择地进行替换。
程序中让人难以理解意图的数值称为幻数(magic number)。我们应尽量避免使用幻数。
代码清单 2-18 引入了变量来表示圆周率。
在程序开始处,将 3.14159 赋给变量 PI,之后使用 PI 进行计算。
作为常量使用(即赋值后不更改)的变量的名字一般只由大写字母和下划线构成,所以此处变量名使用大写字母 PI。
这样修改后的程序有两个优势。
可以在一个地方统一管理单个数值
圆周率的值 3.14159 在程序开头赋给了 PI,如果要修改它(比如改为 3.14159265),只要修改一处代码即可。
这样一来,就能避免输入错误和编辑器替换操作导致的错误,例如 3.14159 和 3.14159265 在程序中混用,或者不表示圆周率但与之相同或相似的数值被错误替换等,提升了程序的可维护性(maintainability)。
程序变得容易阅读
因为可以引用变量名 PI 而非数值作为圆周率,所以程序变得更容易阅读,也就是提升了程序的可读性(readability)。
要点 不应该在程序中使用幻数,要使用名称由大写字母和下划线组成的变量并对变量赋值。
▶ 实际上,Python 提供了变量 math.pi 来表示圆周率。使用该变量的程序(chap02/list0218a.py)如下所示。
# 计算圆的周长和面积(其三:用 math.pi 表示圆周率)
from math import pi
r = float(input(' 半径:'))
print(' 圆的周长是', 2 * pi * r, '。')
print(' 面积是', pi * r * r, '。')
这里从 math 模块引入了变量 pi。我会在第 10 章对 from…import…进行介绍。
专栏 2-1 指定编码
Python 脚本程序中可以指定编码(专栏 13-1)。以下为指定 UTF-8 编码的示例。
# coding: utf-8
但是 Python 程序实现原则 PEP 8(第 81 页)认为,不应该在使用 UTF-8(Python 2 则是 UTF-8 编码,就不需要 ASCII)的文件中对编码进行声明。 因此,在 Python 3 的程序中只要使用了对编码进行声明。
总结
Python 的脚本程序可以保存为扩展名为 .py 的脚本文件。
程序内的语句基本上按照先后顺序执行。
脚本程序内以符号 # 开头的一行内容称为注释,用来向包含程序开发者在内的程序读者传达必要的信息。
注释和空行对程序的执行没有影响。
Python 提供了许多使用方便的内置函数,如 print 函数和 input 函数。
当程序请求函数进行某项处理时,一般会使用调用运算符 (),以函数名 ( 并列的实参 ) 的形式调用函数。
把待显示的任意个字符串作为实参传递给 print 函数,然后调用 print 函数,就能输出字符串。实参中包含 \n 可以使字符串换行显示。
print 函数在输出接收到的参数时,会输出空格来分隔不同参数,最后输出换行符作为结尾。打印输出时在参数中使用 sep=’ 字符串 ’ 可以更改显示时的分隔符,使用 end=’ 字符串 ’ 可以更改显示时的结尾字符。
input 函数会读取通过键盘输入的字符串并返回该字符串。函数读取到行末的换行符,但返回的字符串中不包含换行符。
另外,如果将字符串作为实参传递给 input 函数,程序会先输出该字符串,然后读取键盘的输入。
将字符串转换为整数时,需要调用 int 函数并传递该字符串作为实参。int 函数的第二个参数可以省略,也可以指定为转换基数 2、8、10、16。
将字符串转换为浮点数时需要调用 float 函数。
将数值转换为字符串时,在十进制数的情况下使用 str 函数,在二进制数的情况下使用 bin 函数,在八进制数的情况下使用 oct 函数,在十六进制数的情况下使用 hex 函数。
调用 format 方法后,我们就可以在字符串中插入其他格式化的字符串或数值,从而生成新的字符串。format 方法的调用形式是字符串 .format( 并列的实参 ),字符串中包含 {}。
在脚本程序中直接使用数值字面量可能会产生意义不明的幻数。应使用大写字母和下划线对变量进行命名,然后使用赋值后的变量。
上一章