IMZRH的日志

努力成为一个有用的人

导航

Python学习之三:《Dive in Python》学习笔记二

Posted on 2010-05-13 00:11  张荣华  阅读(3451)  评论(1编辑  收藏  举报

为了丰富一下自己的视野,最近在利用《Dive in python》这本书学习Python,下面是我的读书笔记第二篇,读书笔记和第一篇可以在这里找到

《Dive in python》的第二章中主要利用下面的代码段讲述了Introspection,直译过来有"自省、内省、自我测量"的意思,但我感觉和C#中的反射Reflection有点相似。同第一章一样我们还是先来看代码:

help
def help(object , spacing = 10, collapse = 1):
"""Print methods and doc strings.
Takes module , class, list, dictionary, tuple or 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 help.__doc__

上面的代码主要作用是用指定的格式输出指定对象的方法列表,可能您现在还看不太懂这段代码,不过不要紧,下面让我们来先看看代码中用到的知识点,等知识点都看过后再来看代码就会容易理解的多的。

 

一、可选参数与命名参数

Python中支持可选参数,即在定义函数时给某些参数提供默认值,如果在调用函数时没有指定该参数,则参数使用默认值;另外Python还支持给参数命名,这样便可以用任意顺序来调用函数了。 下面让我们来看一个可选参数和命名参数的例子:

Optional and Named Arguments
def help(object , spacing = 10, collapse = 1): # object is required , spacing and collapse is optional,
# and spaceing have a defalut value 10, collapse have a default value 1.
...
li
= []
help(li)
# with only one parameter, spacing & collaspe gets its default value.
help(li, 20) # with two parameters, spacing's value is 20, collaspe gets its default value 1
help(li,collapse = 0) # with two parametesr , collaspe's value is 0 , spacing gets its default value 10
help(spacing = 100, object = li) # with two parameters, please notice the paramter order.

上面的代码段展示了在Python中如何应用可选参数和命名参数,话说在最近发布的C#4.0中也提供了类似的特性,有兴趣的朋友可以关注下。

 

二、Python内置函数

在Python中大部分代码是以module的形式存在的,但Python也提供了一些内置函数,像type,str, dir等,下面我们分别来看看这些内置函数的作用。

1.type函数

type主要用来返回对象的类型,Python中可用的类型主要在types这个module中定义,type类似于C#中的typeof。下面我们来看代码:

print type(1) # <type 'int'>
print type('2009-1-9 10:20:20') # <type,'str'>
print type([]) # <type, 'list'>
print type({}) # <type, 'dict'>
import types
print type([]) == types.ListType # True

2.str函数

str函数用来强制将一个对象转化成字符串,类似于C#中的ToString()方法, 具体用法见代码:

str
print str(1) # 1
horsmen = ['war', 'pestilence', 'famine'] # declare a list .
horsmen.append('Powerbuilder') # add a new item to list.
print str(horsmen) # ['war', 'pestilence', 'famine', 'Powerbuilder']
print str(None) # None

import help
print str(help) # <module 'help' from 'C:\Users\Administrator.qq-PC\Desktop\help.py'>

在上面的代码中特别需要注意print str(None)这行,str会对None这个Python中的空值返回"None"字符串,我们在help函数中还会用到这个特性。

3.dir函数

dir函数用来返回对象的属性列表和方法列表,这个在C#中没有相似的方法,在C#中要想完成类似操作需要分两步完成,第一步先用GetProperies获得对象属性集合,第二步再用GetMethods获得对象方法集合,从这点上来看Python语法比C#简洁一些。关于dir的使用可以参考以下的代码:

dir
li = []
print dir(li) # ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

d
= {}
print dir(d) # ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

import help
print dir(help) # ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'help']

4.callable函数

callable用来判断一个对象是否是可以调用的,如果对象是可以调用的则callable返回1,否则返回0。关于callable的使用见以下代码:

callabe
import string
print string.punctuation # !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
print string.join # <function join at 0x01B20E70>

print callable(string.punctuation) # False
print callable(string.join) # True
print callable(string) # False


三、getattr函数

通过以前的介绍您可能已经知道在Python中函数也是一个对象,但您有可能不知道通过getattr函数我们还可以在运行时动态调用一个函数,甚至于我们不知道这个函数的名字。个人感觉getattr和C#中的利用反射Invoke一个方法比较相似。getattr的具体使用可以参考下面的代码段:

getattr
li = ["larry", "cruly"]
print li.pop # <built-in method pop of list object at 0x01BF9490>
print getattr(li, "pop") # <built-in method pop of list object at 0x01BF9490>

getattr(li,
"append")("moe")
print li # <built-in method pop of list object at 0x01BF9490>

print getattr({}, "clear") #
print getattr((), "pop") # AttributeError: 'tuple' object has no attribute 'pop'

 

四、 列表过滤(Filtering Lists)

在Pyhon中提供了方便的列表映射功能,我们可能直接在一个表达式中映射列表的部分元素,而在其它语言(比如C#)中完成相应的操作则比较繁琐,在Python中列表过滤的语法规则是:

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

其中mapping-expression是需要返回的表达式,element是一个循环临时变量,source-list是要映射的源列表,filter-expression是过滤表达式,让我们来看一个例子:

filtering lists
li = ["monday", "thesday", "wednesday", "thursday", "friday", "saturday","sunday", "sunday"]
print [elem for elem in li if len(li) > 7] # ['monday', 'thesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'sunday']
print [elem for elem in li if li.count(elem) > 1] # ['sunday', 'sunday']
print [elem + "__YES" for elem in li if len(li) > 7] # ['monday__YES', 'thesday__YES', 'wednesday__YES', 'thursday__YES', 'friday__YES', 'saturday__YES', 'sunday__YES', 'sunday__YES']

 

五、 and or操作符

Python中的and or操作符和C#语言的完成的功能基本一样,但返回值是不同, 在Python和C#中这两个操作符都是用来进行逻辑操作的,在C#中返回值是true/false,但在Python中and or 却返回一个实际的值,下面让我们来看例子 :

print 'a' and 'b' # 'b'
print '' and 'b' # ''
print 0 and '' and 'b' # 0
print 'a' and 'b' and 'c' # 'c'

print 'a' or 'b' # 'a'
print '' or 'b' # 'b'
print '' or 0 or {} # {}

and操作符的取值规律是在单一表达式中除了0,’’,[],(),{},None被当成false,其它的对象一律为true,如果在整个表达式中所有的true,则返回最后一个;如果表达式中有任一个false,则返回第一个为false的内容;

 

or操作符的取值规律是在如果所有的值均为true,则返回第一个元素;如果表达式里即有true,又有false,则返回从左到右的第一个true值;如果所有的值均为false,则返回最后一个false值。

我们知道在C#我们可以利用三目操作符 expression?value1:value2方便的根据条件取得值,在Python中并利用提供这样的操作符,但我们可以利用and or操作符的组合来完成,下面是一个例子:

a = "first"
b
= "second"

print 1 and a or b
print 0 and a or b

利用上面的代码我们可以来模拟C#中的三目操作符, 但上面的代码有个问题,就是当a的值为false时,上面的代码就不能正常工作了,所以我们必须对上面的代码进行调整,具体的调整见下方:

a = ""
b
= "second"

print 1 and a or b # second
print 0 and a or b # second

print (1 and [a] or [b])[0] # ""

 

六、Lambda表达式支持

Python提供了对Lambda表达式的支持,Lambda表达式最早出现了Lisp语言中,现代的很多语言(包括C#3.0)都提供了对Lambda表达式的支持。在Python中如何应用Lambda表达式可以通过下面的代码来看:

def foo(x):
  return x * 2 
print foo(3) # 6
l = lambda x: x * 2
print l(3) # 6
print (lambda x: x *2 )(3) # 6

def foo(x):
return x * 2
print foo(3) # 6
l = lambda x: x * 2
print l(3) # 6
print (lambda x: x *2 )(3) # 6

从上面的代码中我们可以看到利用了Lambda表达式后代码变得简洁了一些,可读性也更好了。 需要注意的是在Python中Lambda表达式的内容只能是一个表达式,如果你要做的事情需要一个表达式以上的语句,那么你就只能先声明一个函数,再调用函数,而不能使用Lambda了。

在我们的help函数中我们是这样利用Lambda表达式的:

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

这句代码的意思是如果collaspe的值不为false,那么将( lambda s : " " .join(s.split()))赋值给processFunc,否则将(lambda s: s)赋值给processFunc。 ( lambda s : " " .join(s.split()))的作用是先将s分隔成独立的单词然后再用空格连接起来,这样的目的是为了去除换行符。以便在打印时不换行。(lambda s: s)的作用是直接返回s,不作任何处理。

 

七、其它小知识

通过前面的介绍您可能知道每一个函数都有一个__doc__属性用来返回函数的说明,但如果您在定义一个函数时没有提供说明,__doc__该如何取值呢? 实际上在这种情况下__doc__的值为None(相当于C#中的null)。

有时我们需要将一些长短不一的字符串对齐显示,这时就需要利用函数在较短的字符串上补空格以使所有字符串都长度相等,在Python中我们可以利用ljust和rjust函数来完成,这两个函数的作用基本上和C#中的PadLeft、PadRight一样,具体看下面的代码:

s = "1234567890"
print s.ljust(2) # '1234567890'
print s.ljust(20) # ' 1234567890'
print s.rjust(20) # '1234567890 '

 

总结

在掌握了前面的知识点后我们再来看help函数是不是很好理解了呢?

help
def help(object , spacing = 10, collapse = 1):
"""Print methods and doc strings.
Takes module , class, list, dictionary, tuple or 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 help.__doc__