Python基础教程【读书笔记】 - 2016/7/7

时间:2023-03-09 07:15:15
Python基础教程【读书笔记】 - 2016/7/7

希望通过博客园持续的更新,分享和记录Python基础知识到高级应用的点点滴滴!

第四波:第5章  条件、循环和其他语句

[总览] 

  深入介绍条件语句和循环语句,随后会看到列表推导式如何扮演循环和条件语句的角色,最后介绍pass、del和exec语句的用法。

[5.1] print和import的更多信息

  首先来看看print和import的几个比较好的特性。  

  对于跟多应用程序来说,使用logging模块日志比print语句更合适。

[5.1.1] 使用逗号输出

  打印多个表达式也是可行的,只要将它们用逗号隔开就好。

  print greeting+',',salutation,name

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

  从模块导入函数的时候,可以使用

  import somemodule

  from somemodule import somefunction

  from somemodule import somefunction,anotherfunction,yetanotherfunction

  from somemodule import *

  from somemodule import somefunction as othername

  可以在语句末尾增加一个as子句,或为整个模块提供别名,也可以为函数提供别名。

[5.2] 赋值魔法

  赋值语句的一些特殊技巧。

[5.2.1] 序列解包

  多个赋值操作可以同时进行:

  x,y,z=1,2,3

  x,y=y,x

  叫做序列解包或可迭代解包---将多个值得序列解开,然后放到变量的序列中。当函数或者方法返回元组(或者其他序列或可迭代对象)时,这个特性尤其有用。

  假设需要获取(和删除)字典中任意的键-值对,可以使用popitem方法,这个方法将键-值作为元组返回,那么这个元组就可以直接赋值到两个变量中:

  scoundrel={'name':'Robin','girlfriend':'Marion'}

  key,value=scoundrel.popitem()

  所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致。

[5.2.2] 链式赋值

  链式赋值是将同一个值赋值给多个变量的捷径。  

[5.2.3] 增量赋值

  增量赋值,对于*、/、%等标准运算符都适用。增量赋值可以让代码更加紧凑和简练,很多情况下会更易读。

[5.3] 语句块:缩排的乐趣

  语句块是在条件为真时执行或者执行多次的一组语句。在代码前放置空格来缩进语句即可创建语句块。使用tab字符也可以缩进语句块,揭示为到下一个tab字符位置的移动,而一个tab字符位置为8个空格。块中的每行都应该缩进同样的量。冒号用来标识语句块的开始,当回退到和已经闭合的块一样的缩进量时,就表示当前块已经结束。

[5.4] 条件和条件语句

  介绍让程序选择是否执行语句块的方法。

[5.4.1] 这就是布尔变量的作用

  真值,也叫做布尔值。

  False、None、0、""、()、[]、{}会被解释器看做假False。其他一切都被解释为真。

  布尔值True和False属于布尔类型,bool函数可以用来转换其他值。

[5.4.2] 条件执行和if语句

  if语句可以实现条件执行,如果条件判定为真,执行后面的语句块。条件为假,不执行。

[5.4.3] else子句

  之所以叫做子句,是因为它不是独立的语句,而只能作为if语句的一部分。

[5.4.4] elif子句

  如果需要检查多个条件,就可以使用elif。

[5.4.5] 嵌套代码块

  if语句里面可以嵌套使用if语句。

[5.4.6] 更复杂的条件

1、比较运算符

  x==y

  x<y

  x>y

  x>=y

  x<=y

  x!=y

  x is y          x和y是同一个对象

  x is not y        x和y是不同的对象

  x in y          x是y容器的成员

  x not in y        x不是y容器的成员

  Python中比较运算和赋值运算一样是可以连接的,几个运算符可以连在一起使用,比如:0<age<100

2、相等运算符

  如果想要知道两个东西是否相等,应该使用相等运算符,即两个等号==。单个相等运算符是赋值运算符,是用来改变值得,而不能用来比较。

3、is:同一性运算符

  is运算符是判定同一性而不是相等性的。变量x和y都被绑定到同一个列表上,而变量z被绑定在另外一个具有相同数值和顺序的列表上。它们的值可能相等,但是却不是同一个对象。

  总结一下:使用==运算符来判定两个对象是否相等,使用is判定两者是否等同(同一个对象)。

4、in:成员资格运算符

5、字符串和序列比较

  字符串可以按照字母顺序排列进行比较。

  字符是按照本身的顺序值排列的,一个字母的顺序之可以用ord函数查看,ord函数与chr函数功能相反。如果要忽略大小写字母的区别,可以使用字符串方法upper和lower。

6、布尔运算符

  and、or、not。

短路逻辑和条件表达式:

  布尔运算符有个有趣的特性:只有在需要求值时才进行求值。举例来说,表达式x and y需要两个变量都为真时才为真,所以如果x为假,表达式就会立刻返回false,而不管y的值。这种行为被称为短路逻辑short-circuit logic或惰性求值。着意味着在布尔运算符之后的所有代码都不会执行。它主要是避免了无用地执行代码。

  a if b else c

  如果b为真,返回a。否则,返回c。注意这个运算符不用隐去临时变量,就可以直接使用。

[5.4.7] 断言

  如果需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert语句就有用了,它可以在程序中置入检查点。

  assert 0<age<100,'The age must be realistic!'

[5.5] 循环

[5.5.1] while循环

  while not name or name.isspace():

    print 'hello ,%s!' %  name

[5.5.2] for 循环

  可迭代对象是指可以按次序迭代的对象。

  Range函数的工作方式类似于分片,它包含下限,但不包含上限。如果希望下限为0,可以只提供上限。

  如果能使用for循环,就尽量不用while循环。

  xrange函数的循环行为类似于range函数,区别在与range函数一次创建整个序列,而xrange一次只创建一个数。当需要迭代一个巨大的序列时,xrange会更高效。

[5.5.3] 循环遍历字典元素

  keys方法来获取键,如果只需要值,可以使用d.values替代d.keys。d.items方法将键-值对作为元组返回。

  字典元素的顺序通常是没有意义的。迭代的时候,字典中的键和值都能保证被处理,但是处理顺序不确定。如果顺序很重要的话,可以讲键值保存在单独的列表中,例如在迭代前进行排序。

[5.5.4] 一些迭代工具

  在python中迭代序列时,一些函数非常有用。有些函数位于itertools模块中,还有一些python的内建函数也十分有用。

  1. 并行迭代

  程序可以同时迭代两个序列。

  names=['anne','beth','george','damon']

  ages=[12,34,32,102]

  for i in range(len(names)):

    print names[i],'is',age[i],'year old!'

  内建的zip函数可以用来进行并行迭代,可以把两个序列“压缩”在一起,然后返回一个元组的列表。

  zip(names,ages)

  [('anne',12),('beth',34),('george',32),('damon',102)]

  for name,age in zip(names,ages):

    print name,'is',age,'years old!'

  zip函数也可以作用于任意多的序列。很重要的一点是zip可以应付不等长的序列,当最短的序列“用完”的时候就会停止。

  zip(range(5),xrange(1000000))

  上面的代码中,不推荐用range替换xrange---尽管只需要前5个数字,但range会计算所有的数字,这要花费很长的时间。而使用xrange就没有这个问题,它只计算前5个数字。

  2. 编号迭代

  要迭代序列中的对象,同时还要获取当前对象的索引。可以使用内建的enumerate函数:

  for index,string in enumerate(strings):

    if 'xxx' in string:

      strings[index]='[censored]'

  3. 翻转和排序迭代

  reversed和sorted:它们同列表的reverse和sort方法类似,但作用于任何序列或可迭代对象上,不是原地修改对象,而是返回翻转或排序后的版本。

  大可在for循环以及join方法中使用,而不会有任何问题。不过却不能直接对它使用索引、分片以及调用list方法。如果希望进行上述处理,那么可以使用list类型转换返回的对象。

[5.5.5] 跳出循环

  1. break  

  2. continue

  跳过剩余的循环体,但是不结束循环。

  3. while true/break习语

  while True:

    word=raw_input('Please enter a word:')

    if not word:break

    print 'The word was '+word

  while True的部分实现了一个永远不会自己停止的循环。但是在循环内部的if语句中加入条件可以的,在条件满足时调用break语句。这样一来就可以在循环内部任何地方而不是只在开头终止循环。if/break语句自然地将循环分为两部分:第1部分负责初始化,第2部分则在循环条件为真的情况下使用第1部分内初始化好的数据。

[5.5.6] 循环中的else子句

  from math import sqrt

  for n in range(99,81,-1)

    root=sqet(n)

    if root==int(root):

      print n

      break

    else:

      print "Didn't find it!"

[5.6] 列表推导式---轻量级循环

  列表推导式list comprehension是利用其它列表创建新列表的一种方法。使用普通的圆括号而不是方括号不会得到“元组推导式”。

[5.7] 三人行

  另外三个语句:pass、del和exec。

[5.7.1] 什么都没有发生

  有的时候,程序什么事情都不用作。pass语句出马了。它可以在代码中做占位符使用。比如程序需要一个if语句,然后进行测试,但是缺少其中一个语句块的代码。因为在python中空代码块是非法的,所以解决方法就是在语句块中加上一个pass语句。

[5.7.2] 使用del删除

  一般来说,python会删除那些不再使用的对象,因为使用者不会再通过任何变量或者数据结构引用它们。

  当把变量设置为None的时候,字典就“漂”在内存里面了,没有任何名字绑定到它上面。没有办法获取和使用它,所以python解释器直接删除了那个字典,这种行为被称为垃圾收集。

  另外一个方法就是使用del语句。它不仅会移除一个对象的引用,也会移除那个名字本身。

  当x和y都指向同一个列表:

  x=['hello','world']

  y=x

  y[1]='python'

  x

  ['hello','python']

  会有人认为删除x之后,y也就随之消失了,但并非如此:

  del x

  y

  ['hello','python']

  为什么会这样?x和y都指向同一个列表。但是删除x并不会影响y。原因就是删除的只是名称,而不是列表本身。事实上,在python中是没有办法删除值得(也不需要过多考虑删除值得问题,因为在某个值不再被使用的时候,python解释器会负责内存的回收)。

[5.7.3] 使用exec和eval执行和求值字符串

  有时候会需要动态地创造python代码,然后将其作为语句执行或作为表达式计算。但这样做会有很严重的潜在安全漏洞,如果程序将用户提供的一段内容中的一部分字符串作为代码执行,程序可能会失去对代码执行的控制。

  1. exec

  执行一个字符串的语句是exec。

  exec "print 'hello,world!'"

  命名空间的概念,或称为作用于scope,是非常重要的知识。现在可以把它想象成保存变量的地方,类似于不可见的字典。所以在程序执行x=1这类赋值语句时,就将键x和值1放在当前的命名空间内,这个命名空间一般来说都是全局命名空间,但这并不是必须的。

  2. eval

  eval用于“求值”是类似于exec的内建函数。exec语句会执行一系列python语句,而eval会计算python表达式,并且返回结果值。

[5.8] 小结

  打印:print语句可用来打印由逗号隔开的多个值。如果语句以逗号结尾,后面的print语句会在同一行内继续打印

  导入:可以使用import as语句进行函数的局部重命名。

  赋值:通过序列解包和链式赋值功能,多个变量赋值可以一次性赋值,通过增量赋值可以原地改变变量。

  块:块是通过缩排使语句成组的一种方法。

  条件:条件语句可以根据条件执行或者不执行一个语句块。if/elif/else。这个主题还有一种叫做条件表达式,行如:a if b else c

  断言:断言简单来说就是肯定某事为真。如果表达式为假,断言就会让程序崩溃。

  循环:可以使用continue语句跳过块中的其他语句然后继续下一次迭代,或者使用break语句跳出循环。

  列表推导式:是看起来像循环的表达式,通过列表推导式,可以从旧列表中产生新的列表,对元素应用函数、过滤掉不需要的元素等等。

  pass、del、exec、eval:pass语句什么都不做,可作为占位符使用。del语句用来删除变量,或者数据结构的一部分,但是不能用来删除值。exec语句用与执行python程序相同的方式来执行字符串。eval函数对写在字符串中的表达式进行计算并且返回结果。

[5.8.1] 有用函数

  chr(n)      当传入序号n时没返回n所代表的包含一个字符的字符串(0≤n<256)

  enumerate(seq) 产生用于迭代的(索引,值)对

  ord(c)      返回单字符字符串的int值

  range([start,],stop[,setp])

  xrange([start,],stop[,setp])   创造xrange对象用于迭代

  zip(seq1,seq2,...)        创造用于并行迭代的新序列

  reversed(seq)          产生seq中值得反向版本,用于迭代

  sorted(seq[,cmp][,key][,reverse])  返回seq中值排序后的列表