我要翻译《Think Python》- 004 第二章 变量, 表达式和语句

 

PDF源文件地址 :  http://www.greenteapress.com/thinkpython/thinkpython.pdf

[自述:这一章内容不多,但是由于时间关系,翻译完成这一章也花了我一周的时间,跟我预想的进度相比已经落后了,得加油了,要不然翻译完整本书就要到猴年马月了。目前离翻译完成还有17章!!!]

第二章

变量, 表达式和语句


2.1 值和类型

  值是程序工作的基本要素,如字符串“Hello,World!”或数字1、2等等。
  这些值属于不同类型:2是一个整数,而“Hello,World!”是字符串,之所以这么命名,是因为它包含了一“串”字符。当然你和解释器都可以识别字符串,那是因为它是用一对引号括起来的。另外你如果不确定值的类型,解释器的type函数可以告诉你。
  毫无疑问,字符串属于str类型,整数是int类型。
  >>> type('Hello, World!')
  <type 'str'>
  >>> type(17)
  <type 'int'>

  需要注意的是,有小数点的数字称之为float型,即“浮点”格式表示的数字。

  >>> type(3.2)
  <type 'float'>

  那如何区分‘17’和‘3.2’这样的值呢?它们看起来像数字,但是它们像字符串一样被引号括起来了。
  >>> type('17')
  <type 'str'>
  >>> type('3.2')
  <type 'str'>
  因此,它们是字符串。
  当你输入一个大整数,你可能会用千分号隔开来表示数字1,000,000,这在Python里面是非法的,但是在实际应用中却是合法的。
  >>> 1,000,000
  (1, 0, 0)
  这当然不是我们所期望的结果!Python把千分号隔开的整数1,000,000解释为一个整数序列。这是本书的第一个语义错误的例子:代码运行没有产生错误,但结果却是“不对”的。


2.2 变量

  编程语言最强大的特性之一就是变量赋值的能力,变量即值引用。
  用赋值语句创建变量并给变量赋值:
  >>> message = 'And now for something completely different'
  >>> n = 17
  >>> pi = 3.1415926535897932
  以上3条赋值语句,第一个建立一个message新变量并赋值了一个字符串,第二个把n赋值为整数17,第三个把π的近似值赋值给变量pi。
  我们在纸上演示给变量赋值的时候,通常是先写下变量名,然后用一个箭头指向变量的值,这种类型的图例我们称之为状态图,因为状态图可以标示每个变量的状态。上面例子的状态图如图2.1所示。

  图2.1


  变量类型即值引用类型。
  >>> type(message)

  <type 'str'>
  >>> type(n)

  <type 'int'>
  >>> type(pi)

  <type 'float'>

 

2.3 变量名和关键字

  程序员通常会选择有具体含义的名字来给变量命名——用来记录变量的作用。
  变量名的长度没有限制,可以包含数字和字母,但是必须以字母开头,推荐首字母小写,当然首字母大写也是合法的变量名(后面你会明白其原因)。
  定义变量名也可以使用下划线“_”,通常用在有多个单词的变量名,例如my_name、airspeed_of_unladen_swallow等。
  如果你定义一个非法的变量名,你将会得到一个语法错误:
  >>> 76trombones = 'big parade'
  SyntaxError: invalid syntax
  >>> more@ = 1000000
  SyntaxError: invalid syntax
  >>> class = 'Advanced Theoretical Zymurgy'
  SyntaxError: invalid syntax
  变量名 76trombones 不是以字母开头,而 more@ 则包含了非法字符“@”,但是class为什么也是错误的呢?那是因为class 是Python的一个关键字。因为解释器运用关键字来识别程序结构,因此关键字是不能用来作为变量名使用的。
  Python 2版本有31个关键字:
    and    del    from    not    while
    as    elif    global    or    with
    assert    else    if    pass    yield
    break    except    import    print
    class    exec    in    raise
    continue    finally    is    return
    def    for    lambda    try
  而在Python 3版本中 exec 不再是关键字,但是多了一个nonlocal 关键字。
  因此,请牢记这些关键字,当解释器报变量名错误的时候你可以检查变量名是否跟关键字重复了。


2.4 运算符和运算

  像表示加法和乘法的运算符是特殊字符,将运算符应用到计算中叫做运算。

  运算符+,-,*,/和**分别表示加法,减法,乘法,除法和幂,用法示例如下:
  20+32    hour-1    hour*60+minute    minute/60    5**2    (5+9)*(15-7)

  在其它一些编程语言中,^表示异或运算,但是在Python中用XOR来表示异或位运算。本书不会讨论位运算,如果你对此感兴趣,请参考与位运算相关的链接:http://wiki.python.org/moin/BitwiseOperators
  在Python2版本中,除法运算可能不像你想象的那样:
  >>> minute = 59
  >>> minute/60
  0
  例子中minute的值为59,在传统算术中59除以60的结果是0.98333,而并不是0.而造成这种差异的原因是Python在执行的时候是向下取整数的,当两个数都是整数的时候,结果也是整数。因此向下取整数就会把小数部分去掉了,因此本例计算结果就是0了。
  在Python3版本中,这个除法运算的结果就是一个浮点数。而新的运算符 // 则表示向下取整数。
  >>> minute/60.0
  0.98333333333333328


2.5 表达式和语句

   一个表达式是值、变量和运算符的组合,值和变量本身都被认为是表达式,因此下面这些表达式都是合法的(假设变量x已经被赋值):

  17
  x
  x + 17


  语句是指Python解释器可以执行的代码单元,我们可以看到两种语句:打印和赋值。从技术上讲表达式也是语句,只是把它们区分开来理解起来可能会显得简单一些,它们之间最大的差别在于:表达式有值,而语句则没有。


2.6 交互模式和脚本模式

  使用解释型语言有一个好处,就是把代码保存为脚本之前,你可以通过交互式的方式测试代码,但是交互模式和脚本模式之间的差异依然容易被混淆。
  例如,你当你把Python当成一个计算器使用,你可能输入:
  >>> miles = 26.2
  >>> miles * 1.61
  42.182
  第一行赋值给变量miles,但是却看不到效果,第二行是一个表达式,所以解释器计算并显示了结果。由此我们得到了马拉松全程长度为大约42公里。
  但是你要是把代码写在脚本里并且运行脚本,你根本看不到输出结果。在脚本模式中,表达式本身并不可见,而Python实际上已经对表达式进行了计算,你只有这样输入才会看到输出结果:
  miles = 26.2
  print miles * 1.61
  最初你可能对解释器的这种行为感到疑惑。
  通常情况下,脚本包含一系列的语句,如果输出代码超过一行以上,那么运行脚本的结果将会一次性的显示出来。
  例如,脚本如下:
  print 1
  x = 2
  print x
  输出结果如下:
  1
  2
  赋值语句不会有输出结果。

 

  练习 1 

  输入以下语句,观察Python解释器的行为。
  5
  x = 5
  x + 1
  然后再把代码放在脚本里并执行该脚本,看看会输出了什么结果。之后把每个表达式改成print语句再运行查看结果。

 

2.7 运算顺序

  当表达始终出现多个运算符的时候,计算顺序取决于优先等级。在算术运算中Python是遵循数学惯例的。英文缩写PEMDAS可一帮助你记住预算规则:
    P - 括号具有最高优先级,可以强制解释器按所需顺序计算,由于括号内的表达式优先计算,因此 2*(3-1) 等于4,(1+1)**(5-2)等于8(**表示幂运算)。你也可以运用括号让表达式更容易阅读,例如 (minute*100)/60 和 minute*100/60 运算结果是一样的。
    E - 幂运算的优先等级次之,所以2**1+1的结果是3,而不是4;3*1**3的结果是3,而不是27.
    MDAS - 乘法和除法具有相同的优先等级,其优先级高于加法和减法,加法和减法则具有相同的优先级。2*3-1等于5,而不是4;6+4/2等于8,而不是5。
  

  优先级相同的运算符按从左到右的顺序计算(指数运算除外),在表达式 degrees / 2 * pi 中,先算除法然后结果再乘以pi。如果改成除以2 π,你可以用括号这样写 degrees/(2*pi)或者写成degrees/2/pi。
  我其实也不愿意花太多时间去记运算符的优先级的,如果我无法解释表达式优先级,我会使用括号让表达式看起来简单一些。

 

2.8 字符串操作

  通常,你不能对字符串进行数学运算,即使字符串看起来像数字,如下所示代码是非法的:
  '2'-'1' 'eggs'/'easy' 'third'*'a charm'
  “+” 运算符在字符串操作中是可行的,但是可能不是你所期望的那样:它执行连接操作,也就是把两个字符串首尾相连。
  例如:
  first = 'throat'
  second = 'warbler'
  print first + second
  输出结果就是 throatwarbler
  “*” 运算符在字符串操作中也是可行的,它执行重复操作,例如:
  'Spam'*3 运算结果是 'SpamSpamSpam',也就是其中一个操作数是字符串,而另外一个必须是一个整数。
  对字符串进行 + 和 * 操作的用法对比是有意义的,就像4*3等同于4+4+4,而'Spam'*3等同于'Spam'+'Spam'+'Spam'一样。另一方面,字符串串联和重复操作跟整数的相加和相乘还是有显著区别的,你能区分这里面的不同属性吗?

 

2.9 注释

  随着程序越来越大,越来越复杂,其阅读难度也是越来越大。正式语言是庞杂晦涩的,通常很难查看其中一段代码就能弄明白它在做什么和这么做的原因。
  出于这个原因,在程序中添加一些用自然语言说明程序的作用的文字就是一个很好习惯。这些说明文字就叫做注释,一般以 # 开始。
  # compute the percentage of the hour that has elapsed
  percentage = (minute * 100) / 60
  在这个例子中,注释内容是单独一行显示的,当然你也可以把注释放在代码行的最后:
  percentage = (minute * 100) / 60 # percentage of an hour
  每一行代码中从 # 开始的内容都会被解释器忽略——这部分内容对程序无任何影响。
  注释在记录程序代码的非明显特性的时候是非常有用,其合理性体现在要能让读者能弄明白代码的作用,因此程序中用注释来解释代码的作用是有必要的。
  当然,这也不是绝对的,像下面这个注释却是多此一举的。
  v = 5 # 赋值5 给变量 v
  而下面这个注释却包含着代码中看不出来的有用的信息
  v = 5 # 5米/秒的速度
  因此,好的变量名可以减少注释的内容,但是太长的变量名又会显得过犹不及,这个地方需要你自行权衡处理。

 

2.10 调试

  此时你最容易犯的语法错误是使用了非法的变量名,就像 class 或 yield,这些关键字是不能作为变量名的,又或者像odd~job和US$,这些变量名包含非法字符。
  你如果在一个变量名中间加一个空格,Python就会认为这是两个没有操作符的操作数:
  >>> bad name = 5
  SyntaxError: invalid syntax
  对于语法错误,错误信息通常没有太大的帮助,最常见的语法错误就是 SyntaxError: invalid syntax 和 SyntaxError: invalid token。
  运行时错误最常见的就是“先用后定义”,也就是在给某变量赋值之前就使用该变量,例如你把一个变量名拼写错了就会发生这个错误:
  >>> principal = 327.68
  >>> interest = principle * rate
  NameError: name 'principle' is not defined
  另外变量名是区分大小写的,例如LaTeX和latex就是不一样的。此时,最容易导致语法错误的情况就是使用变量的顺序。例如:计算1/2 π,你可能会输入如下代码:
  >>> 1.0 / 2.0 * pi
  但是,按优先等级,除法是先进行计算,因此你将会得到的结果是π/2,而不是1/2π。此时Python并不知道你到底想要什么结果,因此在这个例子中你得不到任何报错信息,因而你得到了一个错误的结果。

 

2.11 术语表

  值:
    数据基本单位,如数字或字符串,程序操作等
  类型:
    值的分类。到目前为止有整数,浮点数和字符型。
  整数:
    表示整数的类型
  浮点型:
    用小数表示的数字类型
  字符型:
    表示字符序列的类型
  变量:
    值引用的名称
  语句:
    表示命令或操作的代码。目前为止,语句包含赋值和打印语句。
  赋值:
    为变量赋值的语句
  状态图:
    用来表示变量及其值引用的图形
  关键字:
    编译器用来解析程序的保留字。例如if,def和while等关键字是不能用来作为变量名的。
  运算符:
    用来表示简单计算,如加减乘除或字符串级联的特殊字符
  操作数:
    运算符所操作的值
  向下取整:
    两数相除忽略小数部分
  表达式:
    由变量、运算符、值等表示求得数值的组合
  求值:
    通过操作来简化表达式并获得一个值
  优先法则:
    用于计算涉及多个运算符和操作数的表达式的顺序的规则集
  连接:
    把两个操作数首尾相连
  注释:
    程序中的为了让其他程序员(或任何阅读源代码的人)提供的对程序的执行没有任何影响信息。

 

2.12 练习


练习 2
  假设我们执行以下赋值语句:
  width = 17
  height = 12.0
  delimiter = '.'
  为下面每一个表达式写下运算结果和结果类型(表达式的值)

  1.   width/2
  2.   width/2.0
  3.   height/3
  4.   1 + 2 * 5
  5.   delimiter * 5

  用Python解释器检查你的答案

   

 

练习 3
  练习使用Python作为一个计算器:
  1. 计算半径为 r 的球体体积为:4/3 π r3,半径为5的球体积是多少?提示:392.7 是错的。 

print(4/3*3.14159*5**3)
523.5983333333332

 

  2. 假设一本书的价格是 $24.95,但是书店有40%的优惠,运费每次按第一本书 3$ 计算,超出的其它书按每本 0.75$ 计算。如果购买60本书则需要多少钱?

print('%.2f' % (24.95*(1-0.4)*60+3+0.75*59))
945.45

 

  3. 如果我在 6:52 从家里出发,先慢速跑 1 英里(8分15秒每英里),然后再快跑 3 英里(7分12秒每英里),然后再慢跑1英里,请问我几点能回到家吃早饭?

   

这一题我的解题思路是:先算出跑步一共花了多少分钟,然后跟出发时间减一下,可以算出大概 7:30 能回到家

print((((8*60+15)*2+(7*60+12)*3)/60))
38.1

 

posted @ 2018-10-29 17:42  鬼画符  阅读(436)  评论(4编辑  收藏  举报