自省:Python中万物皆对象,自省是指代码可以查看内存中以对象形式存在的其它模块和函数,获取它们的信息,并对它们进行操作。用这种方法,可以定义没有名称的函数,不按函数声明的参数顺序调用函数,甚至引用事先不知道名称的函数。
Example 4.1 apihelper.py
def info(object, spaci ng=10, col lapse=1): """Print methods and doc strings. Takes module, class, l ist, dictionary, o r string.""" methodList = [method for method in dir(object) if callable(getattr(object, method))] processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s) print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList]) if __name__ == "__main__": print info.__doc__
info函数可以接受任何含有函数或者方法的对象(比如模块,含有对象,比如list,含有方法)作为参数,并打印出对象的所有函数和它们的doc string.
apihelper.py 用法示例
>>> from apihelper import info >>> li = [] >>> info(li) append L.app end(object) -- append object to end count L.coun t(value ) ->integer-- return number of occur rences of value extend L.extend(list) -- extend listbyappe nding list elements index L.index(value) -> integer -- return index of first occurrence of value insert L.insert(index,object) -- insert object before index pop L.pop([ index]) -> item-- remove and return item at index (default last) remove L.remove(value) -- remove first occur rence of value reverse L.reverse() -- reverse *IN PLACE* sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1,0,1
apihelper.py 的高级用法
>>> import odbchelper >>> info(odbchelper) buildConnectionString Build a connection stringfrom adictionary Returns string. >>> info(odbchelper, 30) buildConnectionString Build a connection string from adictionary Returns string. >>> info(odbchelper, 30, 0) buildConnectionString Build aconnection string from adictionary Returns string.
使用可选参数和命名参数
Python允许函数参数有缺省值;如果调用函数时不使用参数,参数将获得它的缺省值。此外,通过使用命名参数还可以以任意顺序指定参数。
info函数就是这样一个例子,它有两个可选参数。
def info(object, spacing=10, collapse=1):
spacing和collaspe是可选参数,因为它们已经定义了缺省值。object是必备参数,因为它没有指定缺省值。
info(odbchelper) (1) info(odbchelper, 12) (2) info(odbchelper, collapse=0) (3) info(spacing=15, object=odbchelper) (4)
(1)只使用一个参数,spacing使用缺省值10,collapse使用缺省值1。
(2)使用两个参数,collapse使用缺省值1。
(3)命名collapse并指定其值。spacing则依然使用它的缺省值10。
(4)必备参数(如object,没有指定缺省值)也可采用命名参数的方式,而且命名参数可以任意顺序出现。
内置函数
str函数能将数据强制转换为字符串。当str函数作用于模块时,模块的字符串形式表示包含了模块在磁盘上的路径名。str函数细小但重要的行为是它可以作用于None,None是Python的null值,这个调用返回字符串’None’。
>>> str(odbchelper) "<module 'odbchelper' from 'c:\\docbook\\dip\\py\\odbchelper.py'>" >>> str(None) 'None'
dir函数可以返回任意对象的属性和方法列表。
>>> li = [] >>> dir(li) (1) ['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] >>> d = {} >>> dir(d) (2) ['clear', 'copy ', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values'] >>> import odbchelper >>> dir(odbchelper) (3) ['__builtins__', '__ doc__', '__ file__', '__ name__', 'buildConnectionString']
(1)dir(li)返回一个包含所有列表方法的列表。返回的列表中只包含了字符串形式的方法名称,而不是方法对象本身。
(2)dir(d)返回一个包含所有字典方法的列表。
(3)dir(odbchelper)返回模块中定义的所有部件的列表,包括内置的属性以及其他定义的属性和方法。
callable函数接受任何对象作为参数,如果参数对象是可调用的,返回True;否则返回False。可调用的对象包括函数、类方法,甚至类自身。
type、str、dir以及其他的Python内置函数都归组到了builtin这个模块中。
通过getattr获取对象引用
通过getattr函数可以得到一个直到运行时才知道名称的函数的引用。
>>> li = ["Larry", " Curly"] >>> li.pop <built-in method pop of list object at 010DF884> >>> getattr(li, "pop") (1) <built-in method pop of list object at 010DF884> >>> getattr(li, "append")("Moe") (2) >>> li ["Larry", "Curly", "Moe"] >>> getattr({}, "clear") (3) <built-in method clear of dictionary object at 00F113D4> >>> getattr((), "pop") (4) Traceback (innermost last) : File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'pop'
(1)该语句是返回pop方法的引用,此时,方法名称是作为一个字符串参数传递给getattr函数的。getattr函数可以返回任何对象的任何属性。
(2)getattr的返回值是方法,就可以调用它。实际上是,并没有直接调用函数,只是以字符串的形式指定了函数名称。
(3)getattr可以作用于字典。
(4)理论上,getattr也可作用于元组,但由于元组没有方法,所以不管指定什么属性名称getattr都会引发一个异常。
getattr不仅适用于内置数据类型,也可作用于模块。
通常,getattr(object,attribute)等价于object.attribute。如果object是一个模块的话,那么attribute可能是定义在模块中的任何东西:函数、类或者全局变量。
getattr常见的使用模式是作为一个分发者。
过滤列表
Python具有通过列表解析将列表映射到其它列表的能力。这种能力同过滤机制结合使用,使列表中有些元素被映射的同时跳过另外一些元素。
过滤列表语法:
[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] (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] (2) ['a', 'mpilgrim', 'foo', 'c']
(1)len方法能够返回字符串中的字符数(包括空格和符号)。
(2)count方法能够返回某个值在列表中出现的次数。
and和or的特殊性质
在布尔环境中,0、”、[]、{}、None为假,其它任何东西都为真。
>>> 'a' and 'b' 'b' >>> '' and 'b' '' >>> 'a' and 'b' and 'c' 'c' >>> 'a' or 'b' 'a' >>> '' or 'b' 'b' >>> '' or [] or {} {}
使用lambda函数
lambda函数允许快速定义单行的最小函数。
>>> def f(x) : ... return x*2 ... >>> f(3) 6 >>> g = lambda x: x*2 (1) >>> g(3) 6 >>> (lambdax: x*2)(3) (2) 6
(1)lambda函数完成了同上面普通函数相同的事。lambda函数里,参数列表的周围没有括号,而且忽略了return关键字。同时,该函数没有函数名,但是可以将它赋值给一个变量进行调用。
(2)使用lambda函数时甚至不需要将它赋值给一个变量。
总的来说,lambda函数可以接受任意多个参数(包括可选参数)并且返回单个表达式的值。lambda函数不能包含命令,包含的表达式不能超过一个。
不带参数的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)通过split分割字符串你可以将空格统一化;然后再以单个空格作为分隔符用jion将其重新连接起来。
processFunc = collapse and (lambdas: " ".join(s.split())) or (lambda s: s)
lambda函数在布尔环境中总是为真(这并不意味着lambda函数不可能返回假值,这个函数对象的布尔值为真;它的返回值可以是任何东西。)此时,如果collapse为真,processFunc(string)将压缩空白;否则processFunc(string)将返回未改变的参数。
print "\n".join(["%s %s" % (1) (method.ljust(spacing), (2) processFunc(str(getattr(object, method).__doc__))) (3) for method in methodList])
(1)这是一条命令,被分隔成了多行,但没有使用续行符(\)。在小括号,方括号或者大括号中的表达式可以用或者不用续行符分割成多行。列表解析就是这些表达式之一,因为整个表达式包括在方括号里。
(2)ljust用空格填充字符串以符合指定的长度。如果指定的长度小于字符串的长度,ljust将简单地返回未变化的字符串,它绝不会截断字符串。
>>> s = 'buildConnectionString' >>> s.ljust(30) 'buildConnectionString ' >>> s.ljust(20) 'buildConnectionString'
(3)getattr函数可以得到object模块中method函数的引用。至于为什么使用str强制将数据转化为字符串,是因为不是每个函数都有doc string,如果没有,这个doc属性为None。processFunc假设收到一个字符串参数然后调用split方法,如果传入的是None,程序就会崩溃,因为None没有split方法。而str函数可以接受值为null的参数,然后返回它的字符串表示,’None’。