您的位置:首页 > 编程语言 > Python开发

Dive Into Python 学习记录3-getattr 介绍/过滤列表/and or/lambda 函数

2012-07-26 16:20 911 查看
3.1getattr 介绍

>>> li = ["Larry", "Curly"]
>>> li.pop


<built-in method pop of list object at 010DF884>
>>> getattr(li, "pop")


<built-in method pop of list object at 010DF884>
>>> getattr(li, 'pop')(3)
'why'
>>> li
['hard', 'difficult', 'complex']                   #也可以用
>>> getattr(li, "append")("Moe")


>>> li
["Larry", "Curly", "Moe"]
>>> getattr({}, "clear")


<built-in method clear of dictionary object at 00F113D4>
>>> getattr((), "pop")


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



该语句获取列表的 pop 方法的引用。注意该语句并不是调用pop 方法;调用
pop 方法的应该是 li.pop()。这里指的是方法对象本身。


该语句也是返回 pop 方法的引用,但是此时,方法名称是作为一个字符串参数传递给getattr 函数的。getattr 是一个有用到令人无法致信的内置函数,可以返回任何对象的任何属性。在这个例子中,对象是一个 list,属性是pop 方法。


如果不确信它是多么的有用,试试这个:getattr 的返回值是 方法,然后你就可以调用它,就像直接使用li.append("Moe") 一样。但是实际上你没有直接调用函数;只是以字符串形式指定了函数名称。


getattr 也可以作用于字典。


理论上,getattr 可以作用于元组,但是由于元组没有方法,所以不管你指定什么属性名称getattr
都会引发一个异常。
3.2 过滤列表

[mapping-expression for element in source-list if filter-expression]

这是你所知所爱的列表解析的扩展。前三部分都是相同的;最后一部分,以if 开头的是过滤器表达式。过滤器表达式可以是返回值为真或者假的任何表达式 (在
Python 中是几乎任何东西)。任何经过滤器表达式演算值为真的元素都可以包含在映射中。其它的元素都将忽略,它们不会进入映射表达式,更不会包含在输出列表中。

>>> li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
>>> [elem for elem in li if len(elem) > 1]


['mpilgrim', 'foo']
>>> [elem for elem in li if elem != "b"]


['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
>>> [elem for elem in li if li.count(elem) == 1]


['a', 'mpilgrim', 'foo', 'c']



这里的映射表达式很简单 (只是返回每个元素的值),所以请把注意力集中到过滤器表达式上。由于
Python 会遍历整个列表,它将对每个元素执行过滤器表达式。如果过滤器表达式演算值为真,该元素就会被映射,同时映射表达式的结果将包含在返回的列表中。这里,你过滤掉了所有单字符的字符串,留下了一个由长字符串构成的列表。


这里你过滤掉了一个特定值 b。注意这个过滤器会过滤掉所有的b,因为每次取出
b,过滤表达式都将为假。


count 是一个列表方法,返回某个值在列表中出现的次数。你可以认为这个过滤器将从列表中剔除重复元素,返回一个只包含了在原始列表中有着唯一值拷贝的列表。但并非如此,因为在原始列表中出现两次的值 (在本例中,b 和d) 被完全剔除了。从一个列表中排除重复值有多种方法,但过滤并不是其中的一种。
在Python 中,and 和
or 执行布尔逻辑演算,如你所期待的一样。但是它们并不返回布尔值,而是返回它们实际值;

3.3 and or

例 4.15. and 介绍

>>> 'a' and 'b'


'b'
>>> '' and 'b'


''
>>> 'a' and 'b' and 'c'


'c'




使用 and 时,在布尔环境中从左到右演算表达式的值。0、''、[]、()、{}、None 在布尔环境中为假;其它任何东西都为真。还好,几乎是所有东西。默认情况下,布尔环境中的类实例为真,但是你可以在类中定义特定的方法使得类实例的演算值为假。你将会在第
5 章中了解到类和这些特殊方法。如果布尔环境中的所有值都为真,那么 and 返回最后一个值。在这个例子中,and 演算'a' 的值为真,然后是
'b' 的演算值为真,最终返回 'b'。


如果布尔环境中的某个值为假,则 and 返回第一个假值。在这个例子中,'' 是第一个假值。


所有值都为真,所以 and 返回最后一个真值,'c'。

例 4.16. or 介绍

>>> 'a' or 'b'


'a'
>>> '' or 'b'


'b'
>>> '' or [] or {}


{}
>>> def sidefx():
...     print "in sidefx()"
...     return 1
>>> 'a' or sidefx()


'a'
>>> '' or 'b' or 'd'
'b'




使用 or 时,在布尔环境中从左到右演算值,就像
and 一样。如果有一个值为真,or 立刻返回该值。本例中,'a' 是第一个真值。


or 演算
'' 的值为假,然后演算 'b' 的值为真,于是返回 'b' 。


如果所有的值都为假,or 返回最后一个假值。or 演算'' 的值为假,然后演算
[] 的值为假,依次演算 {} 的值为假,最终返回
{} 。


注意 or 在布尔环境中会一直进行表达式演算直到找到第一个真值,然后就会忽略剩余的比较值。如果某些值具有副作用,这种特性就非常重要了。在这里,函数sidefx 永远都不会被调用,因为
or 演算 'a' 的值为真,所以紧接着就立刻返回
'a' 了。
如果你是一名 C 语言黑客,肯定很熟悉bool ?
a :b 表达式,如果
bool 为真,表达式演算值为a,否则为 b。基于
Python 中 and 和
or 的工作方式,你可以完成相同的事情。

>>> a = ""
>>> b = "second"
>>> (1 and [a] or [b])[0]


''




由于
[a] 是一个非空列表,所以它决不会为假。即使a 是0
或者'' 或者其它假值,列表[a]
也为真,因为它有一个元素。
到现在为止,这个技巧可能看上去问题超过了它的价值。毕竟,使用 if 语句可以完成相同的事情,那为什么要经历这些麻烦事呢?哦,在很多情况下,你要在两个常量值中进行选择,由于你知道a 的值总是为真,所以你可以使用这种较为简单的语法而且不用担心。对于使用更为复杂的安全形式,依然有很好的理由要求这样做。例如,在Python 语言的某些情况下
if 语句是不允许使用的,比如在lambda 函数中。

3.4 使用 lambda 函数

>>> s = "this   is\na\ttest"


>>> print s
this   is
a	test
>>> print s.split()


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


'this is a test'



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


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


通过
split 分割字符串你可以将空格统一化;然后再以单个空格作为分隔符用 join 将其重新连接起来。这也就是info 函数将多行
doc string 合并成单行所做的事情。
那么 info 函数到底用这些 lambda 函数、split 函数和and-or 技巧做了些什么呢?

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


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

在一个不很健壮的语言中实现它,像 Visual Basic,你很有可能要创建一个函数,接受一个字符串参数和一个collapse 参数,并使用
if 语句确定是否压缩空白,然后再返回相应的值。这种方式是低效的,因为函数可能需要处理每一种可能的情况。每次你调用它,它将不得不在给出你所想要的东西之前,判断是否要压缩空白。在Python 中,你可以将决策逻辑拿到函数外面,而定义一个裁减过的
lambda 函数提供确切的 (唯一的) 你想要的。这种方式更为高效、更为优雅,而且很少引起那些令人讨厌 (哦,想到那些参数就头昏) 的错误

3.5 ljust 方法介绍

>>> s = 'buildConnectionString'

>>> s.ljust(30)



'buildConnectionString '

>>> s.ljust(20)



'buildConnectionString'



ljust 用空格填充字符串以符合指定的长度。info 函数使用它生成了两列输出并将所有在第二列的doc string 纵向对齐。


如果指定的长度小于字符串的长度,ljust 将简单地返回未变化的字符串。它决不会截断字符串。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: