Welcome to 陈俊峰's ---BeetleHeaded Man Blog !

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  58 随笔 :: 32 文章 :: 18 评论 :: 0 Trackbacks

Note One:about sequences and lists

序列是不可变列表。一旦创建了一个序列就不能以任何方式改变它。

例 1.21. 定义序列

>>>
t = ("a", "b", "mpilgrim", "z", "example")
1
>>> t
('a', 'b', 'mpilgrim', 'z', 'example')
>>> t[0]
2
'a'
>>> t[-1]                                     
3
'example'
>>> t[1:3]                                    
4
('b', 'mpilgrim')

1 序列的定义同列表的定义方式相同,除了整个元素集是用小括号包围的而不是方括号。
2 序列的元素象列表一样按定义的次序进行排序。序列的索引象列表一样从0开始,所以一个非空序列的第一个元素总是 t[0]
3 负数索引象列表一样从序列尾部开始计数。
4 分片也可以使用,就象列表一样。注意当分割一个列表时,会得到一个新的列表;当分割一个序列时,会得到一个新的序列。

例 1.22. 序列没有方法 

>>>  t
('a', 'b', 'mpilgrim', 'z', 'example')
>>>  t.append("new") 
 
Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'append'

>>>  t.remove("z")  
             
Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'remove'

>>> t.index("example")  
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'index'

>>>"z" in t  
1   

1 你不能向序列增加元素。序列没有 appendextend 方法。
2 你不能从序列中除掉元素。序列没有 remove pop 方法。
3 你不能在序列中查找元素。序列没有 index 方法。
4 然而,你可以使用 in 来看一看是否一个元素存在于序列中

那么序列有什么好处呢?

  • 序列比列表操作速度快。如果你定义了一个值集合常量,并且唯一要用它做的是不断地遍历它,使用序列代替列表。
  • 记得我说过 字典关键字 可以是整数,字符串和“几种其它的类型”吗?序列就是那些类型之一。序列可以在字典中被用作关键字,但是列表不行。[2]
  • 序列用在字符串格式化,这一点我们会很快看到。

Note Two : Mapping in the Lists

列表映射介绍 
      
>>>  li = [1, 9, 8, 4]
>>>  [elem*2 for elem in li]
      1
[2, 18, 16, 8]
>>>  li                     
2
[1, 9, 8, 4]

1

为了对这一点有一个感性认识,从右向左看它。 li 是一个将要映射的列表。Python循环遍历 li 一次一个元素,临时将每个元素的值赋给变量 elem。然后Python使用函数 elem*2 ,接着将结果追加到返回列表中。

2 意列表映射不改变被映射的列表。

Note Three :好东西 lambda 函数

Python支持一种有趣的语法,它允许你快速定义单行的最小函数。这些叫做 lambda 的函数是从Lisp中借用来的,可以被用在任何需要函数的地方。

出于历史的原因,lambda 函数的语法与通常的函数有些细微的不同。

例 2.20. lambda 函数介绍
>>> def f(x):          1
...     return x*2
...    
>>> f(3)
6
>>> g = lambda x: x*2 
2
>>> g(3)
6
>>> (lambda x: x*2)(3)
3
6

1

这是一个通常的函数声明,尽管以前你可能没有看到过定义在交互式窗口中的函数。这个 ... 说明它是一个多行的交互语句。只要在第一行的后面敲入回车,Python IDE会让你接着输入命令。

2

这是一个 lambda 函数,它完成同上面普通函数相同的事情。注意这里的简短的语法;没有小括号, return 是默认的,并且函数没有名字,只有将它赋值给变量的变量名。

3

你甚至可以不将 lambda 函数赋值给一个变量而使用它。这不是举世无双的东西,它只是展示了 lambda 函数只是一个内联函数。

总之, lambda 函数是一个可以接收任意多个参数(包括 可选参数 )并且返回单个表达式值的函数。 lambda 函数不能包含命令,它们所包含的表达式不能超过一个。不要试图向 lambda 函数中塞入太多的东西;如果你需要更复杂的东西,应该定义一个普通函数,然后想让它多长就多长。

Note
lambda 函数是风格问题。不一定非要使用它们,任何能够使用它们的地方,都可以定义一个分离的普通的函数,用它来替换。我将它们用在需要封装特殊的,非重用的代码上,用许多小的一行函数不会弄乱我的代码。

例 2.21. 在 in apihelper.py 中的 lambda 函数 
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)

顺便这里有几件事情需要注意。首先,我们使用了 and-or 技巧的简单形式,没问题,因为一个 lambda 函数 在一个布尔环境下 总为真。(这并不意味着 lambda 函数不能返回假值。函数本身总是为真,它的返回值可以为任何值。)

第二,我们使用了 split 函数没带参数。你已经看到过它带 1个或2个参数 的使用,但是不带参数它按空白进行分割。

例 2.22. split 不带参数    
>>>s = "this   is\na\ttest"         1
>>>print s
  
 this   is
a test

>>>print s.split()
      2
['this', 'is', 'a', 'test']
>>>print   " ".join(s.split())
        3
'this is a test'    

1

这是一个多行字符串,通过转义字符的定义代替了 三重引号 \n 是一个回车; \t 是一个制表符。

2

split 不带参数按空白进行分割。所以三个空格,一个回车,和一个制表符都是一样的。

3

你可以将空白统一化,通过分割一个字符串,然后用单个空格作为分隔符将其重新接起来。这就是 help 函数所做的,将多行文档字符串合并成单行。

那么 help 函数到底用这些 lambda 函数, split 函数,和 and-or 技巧做了什么呢?

例 2.23. 将函数赋给一个变量

				 processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
		

processFunc 现在是一个函数,但它为哪一个函数要看 collapse 变量的值。如果 collapse 为真, processFunc(string) 将压缩空白;否则,processFunc(string) 将返回未改变的参数。

在一个不很建壮的语言实现它,象VB,你将可能创建一个函数,它接收一个字符串和一个 collapse 参数,使用一个 if 语句来判断是否要压缩空白或不压缩,然后返回相应的值。这样效率低,因为函数将不得不处理每种可能性;每次你调用它,它将不得不在给出你所想要的东西之前,判断是否要压缩空白。在Python中,你可以将那种判断逻辑拿到函数外面,而定义一个裁减过的 lambda 函数来给出确切的(并且唯一)你想要的。这样做更有效率,更漂亮,并且更少导致那些令人讨厌的(哦,想到那些参数就头昏)的错误。

posted on 2006-04-13 21:49 Jeff-Chen 阅读(281) 评论(0)  编辑 收藏 引用 所属分类: Python

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理