2.2 简单语句

学习编程序,就好比小学生学习写作一样,先学会一些词语,就等同于已经掌握了基本的对象类型,接下来就是学“造句子”的时候了。

在编程语言中,句子被称之为“语句”。

事实上,前面已经用过语句了,最典型的print"Hello,World"就是语句。

为了能够严谨地阐述这个概念,抄一段维基百科中的词条:命令式编程。

命令式编程(英语:Imperative programming),是一种描述电脑所需做出的行为的编程范型。几乎所有电脑的硬件工作都是指令式的;几乎所有电脑的硬件都是设计来运行机器码,使用指令式的风格来写的。较高级的指令式编程语言使用变量和更复杂的语句,但仍依从相同的范型。

运算语句一般来说都表现了在存储器内的数据进行运算的行为,然后将结果存入存储器中以便日后使用。高级命令式编程语言更能处理复杂的表达式,可能会产生四则运算和函数计算的结合。

一般高级语言都包含如下语句,Python也不例外。

(1)循环语句:容许一些语句反复运行数次。可依据一个默认的数目来决定运行这些语句的执行次数;或反复运行它们,直至某些条件改变。

(2)条件语句:容许仅当某些条件成立时才运行某个区块。否则,这个区块中的语句会略去,然后按区块后的语句继续运行。

(3)无条件分支语句:容许运行顺序转移到程序的其他部分之中。包括跳跃(在很多语言中称为Goto)、副程序和Procedure等。

循环、条件分支和无条件分支都是控制流程。

当然,Python中的语句还是有自己的特别之处的(别的语言也有自己的特色)。下面就开始娓娓道来。

2.2.1 print

在Python 2.x中,print是一个语句,但是在Python 3.x中它就是一个函数了。不过,这里所演示的还是Python 2.x。

print发起的语句,在程序中主要是将某些东西打印出来,还记得在字符串的格式化输出吗?那就是用来print的。

  1. >>> print "hello, world"
  2. hello, world
  3. >>> print "hello", "world"
  4. hello world

请仔细观察上面两个print语句的差别。第一个打印的是“hello,world”,包括其中的逗号和空格,是一个完整的字符串。第二个打印的是两个字符串,一个是“hello”,另外一个是“world”,两个字符串之间用逗号分隔。

本来,在print语句中,字符串后面会接一个\n符号,即换行。但是,如果要在一个字符串后面跟着逗号,那么换行就取消了,意味着两个字符串“hello”和“world”打印在同一行。

或许现在体现得还不是很明显,换一个方法就显示出来了。(下面用到了一个称为for循环的语句,后面要详细讲述。)

  1. >>> for i in [1,2,3,4,5]:
  2. ... print i
  3. ...
  4. 1
  5. 2
  6. 3
  7. 4
  8. 5

这个循环的意思就是要从列表中依次取出每个元素,然后赋值给变量i,并用print语句打印打出来。在变量i后面没有任何符号,每打印一个就换行,再打印下一个,这就是那个“\n”起的作用。

下面的方式就跟上面的有点区别了。

  1. >>> for i in [1,2,3,4,5]:
  2. ... print i ,
  3. ...
  4. 1 2 3 4 5

在print语句的最后加了一个逗号,打印出来的就在一行了。

print语句经常用在调试程序的过程,让我们能够知道程序在执行过程中产生的结果。

2.2.2 import

曾经用到过一个Python标准库math,它能提供很多数学函数,但是这些函数不是Python的内建函数,而是属于math的,所以,要用import math来引入这个标准库。

这种用import引入模块(或者库、包)的方法是Python编程经常用到的。引用方法有如下几种:

  1. >>> import math
  2. >>> math.pow(3,2)
  3. 9.0

这是常用的一种方式,而且非常明确,math.pow(3,2)就明确显示了,pow()函数是math模块里的。可以说这是一种可读性非常好的引用方式,并且不同模块的同名函数不会产生冲突。

  1. >>> from math import pow
  2. >>> pow(3,2)
  3. 9.0

这种方法就有点偷懒了,不过也不难理解,从字面意思就知道pow()函数来自于math模块。在后续使用的时候,只需要直接使用pow()即可,不需要在前面写上模块名称了。这种引用方法,比较适合于引入模块较少的时候。如果引入模块多了,可读性就下降了,会不知道哪个函数来自哪个模块。

  1. >>> from math import pow as pingfang
  2. >>> pingfang(3,2)
  3. 9.0

这是在前面基础上的发展,把从某个模块引入的函数重新命名,比如讲pow重命名为pingfang,然后使用pingfang()就相当于使用pow()了。

还会遇到要引入多个函数的情况,可以这样做:

  1. >>> from math import pow, e, pi
  2. >>> pow(e,pi)
  3. 23.140692632779263

引入了math模块里面的pow、e、pi,pow()是一个乘方函数,e就是欧拉数;pi就是π。

e,作为数学常数,是自然对数函数的底数。有时称它为欧拉数(Euler's number),以瑞士数学家欧拉命名;还有个较鲜见的名字是纳皮尔常数,以纪念苏格兰数学家约翰·纳皮尔引进对数。它是一个无限不循环小数。e=2.71828182845904523536(《维基百科》)

e的π次方,是一个数学常数,与e和π一样是一个超越数。这个常数在希尔伯特第七问题中曾提到过。(《维基百科》)

  1. >>> from math import *
  2. >>> pow(3,2)
  3. 9.0
  4. >>> sqrt(9)
  5. 3.0

这种引入方式是最省事的了,一下将math中的所有函数都引过来了。“好事成双”往往都是梦想,这样引入模块中的函数,其可读性难免降低了,一般适用于模块中的函数比较少的时候,并且在程序中应用比较频繁的情况。

以上用math模块为例,引入其中的函数,其实在编程中,各样的对象都可以引入。

2.2.3 赋值

大家对于赋值语句应该不陌生,在前面已经频繁使用了,如a=3这样的,就是将一个整数赋给了变量。

编程中的“=”和数学中的“=”是完全不同的。在编程语言中,“=”表示赋值过程。

除了那种最简单的赋值之外,还可以这么做:

  1. >>> x, y, z = 1, "python", ["hello", "world"]
  2. >>> x
  3. 1
  4. >>> y
  5. 'python'
  6. >>> z
  7. ['hello', 'world']

这里就一一对应赋值了。如果把几个值赋给一个,可以吗?

  1. >>> a = "itdiffer.com", "python"
  2. >>> a
  3. ('itdiffer.com', 'python')

原来是将右边的两个值装入了一个元组,然后将元组赋给了变量a。Python太聪明了。

在Python的赋值语句中,还有更聪明的。

有两个变量,其中a=2,b=9。现在想让这两个变量的值对调,即最终是a=9,b=2。

这是一个简单而经典的题目。在很多编程语言中,是这样处理的:

  1. temp = a;
  2. a = b;
  3. b = temp;

在这里变量就如同一个盒子,值就如同放到盒子里面的东西。如果要实现对调,必须再找一个盒子,将a盒子里面的东西(数字2)拿到那个临时盒子(temp)中,这样a盒子就空了,然后将b盒子中的东西(数字9)拿到a盒子中(a=b),完成这步之后,b盒子是空的了,最后将临时盒子里面的那个数字2拿到b盒子中。这就实现了两个变量值的对调。

Python只要一行就完成了。

  1. >>> a = 2
  2. >>> b = 9
  3.  
  4. >>> a, b = b, a
  5.  
  6. >>> a
  7. 9
  8. >>> b
  9. 2

a,b=b,a就实现了数值对调,多么神奇。之所以神奇,是因为前面已经数次提到的Python中变量和数据对象的关系。变量相当于贴在对象上的标签,这个操作只不过是将标签换个位置,就分别指向了不同的数据对象。

还有一种赋值方式,被称为“链式赋值”。

  1. >>> m = n = "I use python"
  2. >>> print m, n
  3. I use python I use python

用这种方式实现了一次性对两个变量赋值,并且值相同。

  1. >>> id(m)
  2. 3072659528L
  3. >>> id(n)
  4. 3072659528L

用id()来检查一下,发现两个变量所指向的是同一个对象。

另外,还有一种判断方法,可以检查两个变量所指向的值是否是同一个(注意,同一个和相等是有差别的。在编程中,同一个就是id()的结果一样)。

  1. >>> m is n
  2. True

这是在检查m和n分别指向的对象是否是同一个,True说明是同一个。

  1. >>> a = "I use python"
  2. >>> b = a
  3. >>> a is b
  4. True

这跟上面的链式赋值是等效的。

但是:

  1. >>> b = "I use python"
  2. >>> a is b
  3. False
  4. >>> id(a)
  5. 3072659608L
  6. >>> id(b)
  7. 3072659568L
  8.  
  9. >>> a == b
  10. True

看出其中的端倪了吗?这次a、b两个变量虽然相等,但不是指向同一个对象。

还有一种赋值形式,如果从数学的角度看是不可思议的,如x=x+1,在数学中,这个等式是不成立的,因为数学中的“=”是等于的含义,但是在编程语言中成立,因为“=”是赋值的含义,即将变量x增加1之后,再把得到的结果赋给变量x。

这种变量自己变化之后将结果再赋值给自己的形式,称为“增量赋值”。+、-、*、/、%都可以实现这种操作。

为了让这个操作写起来省点事儿,可以写成:x+=1,如

  1. >>> x = 9
  2. >>> x += 1
  3. >>> x
  4. 10

除了数字,在实际中字符串进行增量赋值也很有价值。

  1. >>> m = "py"
  2. >>> m += "th"
  3. >>> m
  4. 'pyth'
  5. >>> m += "on"
  6. >>> m
  7. 'python'