|
- 示例代码:
from types import BuiltinFunctionType, BuiltinMethodType, \
FunctionType, MethodType, ClassType
def help(object, spacing=10, collapse=1):
"""Print method and doc string.
Takes module, class, list, dictionary, or string."""
typeList = (BuiltinFunctionType, BuiltinMethodType, FunctionType. MethodType, ClassType)
methodList = [method for method in dir(object) if type(getattr(object, method)) in typeList]
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 i n methodList])
if __name__ == "__main__":
print help.__doc__
- 自省综述:根据上边示例代码分析
- 这个模块有一个函数,help, 有三个参数object, spacing, collapse, 后两个是可选参数
- 函数的代码是缩排的,help函数有一个多行的文档字符串,并没有返回值,因为函数只使用他的效果并非它的值
- __name__技巧只是用于测试模块,在别的程序引入这个模块的时候不会引起冲突,
- help函数的设计是为了在ide环境下是用的,接受任何拥有函数或者方法的对象,打印出对象所有的函数和文档字符串
- 用法举例
>>> from apihelper import help
>>> li = []
>>> help(li)
append L.append(object) -- append object to end
count L.count(value) -> integer -- return number of occurrences of value
extend L.extend(list) -- extend list by appending 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 occurrence of value
reverse L.reverse() -- reverse *IN PLACE*
sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
- 高级用法:注意参数变化
>>> import odbchelper
>>> help(odbchelper)
buildConnectionString Build a connection string from a dictionary Returns string.
>>> help(odbchelper, 30)
buildConnectionString Build a connection string from a dictionary Returns string.
>>> help(odbchelper, 30, 0)
buildConnectionString Build a connection string from a dictionary
Returns string.
- 导入模块:两种导入模块的方法
- 基本的from module import 语法
from types import BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, ClassType
注意:与module导入方法类似,但是,导入模块types的属性和方法被直接导入到局部名字空间中,使用的时候不用模块的名字来限定;
- import 和 from module import 对比
>>> import types #只是有每个对象类型的属性
>>> types.FunctionType #必须用module 名称来限定
>>> FunctionType #没有定义在当前的名字空间中,只是存在与types的上下问环境当中
Traceback (most recent call last):
File "", line 1, in
NameError: name 'FunctionType' is not defined
>>> from types import FunctionType
>>> FunctionType
- 什么时候要用from module import
- 如果想经常存取模块的属性和方法,但是不想一遍遍的敲入模块名称
- 想选择性的导入某些属性和方法,不想要其他的
- 如果模块包含的属性或者方法和你自己的某个模块名字相同,只能用import module
- 可选和定名参数(指定参数名字):
- help的合法调用
help(odbchelper)
help(odbchelper, 12)
help(odbchelper, collapse=0) #spacing 缺省
help(spacing=15, object=odbchelper) #object可以定名,任意顺序都行
- type,str,dir和其他内置函数:
- type:返回任意对象的数据类型
>>> type("333")
>>> li=[]
>>> type(li)
>>> import odbchelper
>>> type(odbchelper)
>>> import types
>>> type(odbchelper) == types.ModuleType
True
- str:强制将数据转换为字符串
>>> str(1)
'1'
>>> ho = ["sd", 1, "sdd"] #可以工作于任何类型的任何对象
>>> str(ho)
"['sd', 1, 'sdd']"
>>> str(odbchelper) #模块的字符串表示包含了模块在磁盘上的路径
""
>>> str(None) #python空值 返回字符串 很重要???
'None'
- dir:help函数的核心,返回任意一个对象的属性和方法的列表:模块,函数,字符串,列表,字典... 相当多的东西
>>> li = []
>>> dir(li)
['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> d = {}
>>> dir(d)
['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values']
>>> import odbchelper
>>> dir(odbchelper) #模块,返回模块中定义的所有东西,包括自定义的
['__builtins__', '__doc__', '__file__', '__name__', 'buildConnectionString']
- 内置属性和函数
>>> from apihelper import help
>>> help(__builtins__, 20)
ArithmeticError Base class for arithmetic errors.
AssertionError Assertion failed.
AttributeError Attribute not found.
EOFError Read beyond end of file.
EnvironmentError Base class for I/O related errors.
Exception Common base class for all exceptions.
FloatingPointError Floating point operation failed.
IOError I/O operation failed.
[...snip...]
???
- 综合:type dir str, 以及所有其他的python内置函数一样被组合进入一个名字叫做__builtins__的特别模块中,python启动的时候自动from __builtins__ import * 可以直接使用,好处是,可以通过得到builtins的信息,作为一个组,存取所有内置的函数和属性,help函数实现了那个功能。???
- 使用getattr得到对象的各种引用:可以得到一个直到运行时候才知道的函数的引用???
- getattr介绍
>>> li=["larry", "curly"]
>>> li.pop #得到列表的pop方法的一个引用,并不是调用pop方法,而是方法本身
>>> getattr(li, "pop") #也返回pop方法的一个引用,但是,方法的名字被指定为一个字符串参数,getattr可以返回任意对象的任意属性,在这个例子中,对象是列表,属性是pop方法
>>> getattr(li, "append")("moe") #li.append("moe") 返回值是方法,没有直接调用方法,而是把函数名当作字符串来指定。
>>> li
['larry', 'curly', 'moe']
>>> getattr({}, "clear") #也可以用给字典
>>> getattr((), "pop") #理论上可以用个序列,但是序列没有方法,所以不管给出什么属性名,getattr都将引发一个异常,
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'tuple' object has no attribute 'pop'
- 用于apihelper.py, 不仅可以用于内置数据类型,也可以用于模块
>>> import odbchelper
>>> odbchelper.buildConnectionString #返回在odbchelper模块中的bulidConnectionString函数的引用
>>> getattr(odbchelper, "buildConnectionString") #使用getattr,我们可以得到同一函数的同一引用。 相当于object.attribute. 如果object是一个模块,那么attribute可以是模块中的任何东西:函数,类,或者全局变量。
>>> object = odbchelper
>>> method = "buildConnectionString"
>>> getattr(object, method) #help函数中用到的东西,method字符串是方法或者函数的名字。
>>> type(getattr(object, method)) 本地方method是一个函数的名字
>>> import types
>>> type(getattr(object, method)) == types.FunctionType
True
- 过滤列表:python强大的列表映射到其他列表的能力,同一种过滤机制合并,列表中的某个元素被映射,其他的都忽略掉。
- 列表过滤语法
[mapping-expression for element in source-list if filter-expression]
以if开头的就是过滤表达式,可以是任意真假的表达式,任何对于过滤表达式计算出真值的元素将包括在映射中,其他元素忽略掉,他们不会出现在映射表达式中,也不包括在输出列表中。
- 列表过滤介绍
>>> 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"] # 过滤掉特殊值b,每次b出来过滤表达式都不成立
['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
>>> [elem for elem in li if li.count(elem) == 1] #count返回的是一个元素出现的次数
['a', 'mpilgrim', 'foo', 'c']
- apihelper.py中过滤列表
typeList = (BuiltinFunctionType, BuiltinMethodType, FunctionType, MethodType, ClassType)
methodList = [method for method in dir(object) if type(getattr(objec, method)) in typeList]
看上去挺复杂,但是基本结构是一样的。整个表达式返回一个列表,列表赋给变量methodList,前半部分是列表映射部分,dir(object)返回一个对象的属性和方法的列表,就是正在映射的列表。表达式getattr(object, method)返回一个函数对象,method是模块中的函数名字,这个表达式接受一个object对象,获得它的属性方法,和一些其他东西的名字列表,然后过滤列表,执行过滤通过得到每个属性方法函数的名字,让后通过getattr函数得到指向实际东西的引用。然后用type检查对象类型,我们关心方法和函数,不关心其他属性。classType对象现在不用担心,后边将讨论python的类。
- and-or技巧:要对比bool?a:b 理解其如何工作
>>> a = "first"
>>> b = "second"
>>> 1 and a or b #类似c
'first'
>>> 0 and a or b #类似c
'second'
>>> a = ""
>>> 1 and a or b #区别,看成纯粹的布尔逻辑去分析。
'second'
>>> a = ""
>>> b = "second"
>>> 1 and a or b
'second'
>>> 0 and a or b
'second'
>>> (1 and [a] or )[0] [a] 是一个非空列表 永远为真,
''
Python 中很多时候,不允许使用if语句,一个负责的的程序猿应该将and or 技巧封装成函数:
def choose(bool, a, b):
return (bool and [a] or )[0]
???
- 使用lambda函数:快速定义单行的最小函数,可以被用在任何需要函数的地方,函数的语法通常与其他函数有点不同???
- lambda函数介绍
>>> def f(x):
... return x*2
...
>>> f(2)
4
>>> g = lambda x: x*2 #lambda函数, 没有小括号,return是默认的,函数没有名字。只有将它赋值给变量的变量名g
>>> g(3)
6
>>> (lambda x: x*2)(3) #可以不赋值给一个变量然后使用它,证明是一个内联函数
6
可以接收任意多个参数(包括可选参数)值并且返回单个表达式的值的函数,lambda函数不能包括命令,表达式不能超过一个,不要赛入过多东西。
lambda函数是风格问题,不一定非要使用,许多小的一行代码不会弄乱我的代码,用在需要特殊封装的,非重用的代码上。
- 例子中的lambda函数
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
lambda函数在一个布尔环境下总为真,并不意味着不能返回假值,函数本身总是真,返回值可以任何值。
- split不带参数:上边式子中不带参数
>>> s = "this is\na\ttest"
>>> print s
this is
a test
>>> print s.split() # split不带参数按空白进行分割!!!
['this', 'is', 'a', 'test']
>>> print " ".join(s.split()) #将空白统一化!!!
'this is a test'
- 将函数赋给一个变量
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
processFunc现在是一个函数,但是函数为哪一个要看collapse的值。如果为真processFunc(string)将压缩空白,否则,将返回未改变的参数。
- 注意:其他不健壮的语言实现它,可能创建一个函数,它接收一个字符串和一个collapse函数,使用一个If语句来判断是否需要压缩空白或者不压缩,然后返回相应的值,但是这样效率比较低,每次调用它,不得不再给出想要的东西之前,判断是否空白。在python中,可以将这种判断逻辑拿到函数之外,定义一个裁剪过的函数lambda来给出确切的(唯一的)你想要的。这样做更有效率更漂亮,并且更少导致那些令人讨厌的错误???
- 全部放在一起:所有的多米诺骨牌拼接到一起了,然后将它推倒吧。
print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList])
- 最后一句告诉我们这是一个列表映射,methodLIst是一个在object中所有我们关心的方法的列表。我们用method遍历列表
- 动态得到文档字符串
>>> import odbchelper
>>> object = odbchelper #object是我们要得到的帮助的对象
>>> method = 'buildConnectionString' #method 是当前方法的名字
>>> getattr(object, method) #得到在object模块中对于method函数的一个引用
>>> print getattr(object, method).__doc__ #打印文档字符串
Build a connection string from a dictionary of parameters.
Returns string.
#至于str 是一个 内置函数,强制转换数据,但是不是每个函数都有文档字符串,如果没有的话,__doc__属性是None.
- 为什么对一个文档字符串使用str
>>>{}.keys__doc__
>>>{}.keys__doc__ == None
1
>>>str({}.keys__doc__) #使用str函数就接收了空值,返回它的字符串表示
None
然后保证有了字符串,传递字符串给processFunc,这个函数定义了一个要不要压缩空白或者不压缩,因为process假定一个字符串参数,并且调用了split方法,如果传给的是方法None,而不是字符串,函数就会失败了。
- ljust方法介绍
>>>s = "build"
>>>s.ljust(30) #用空格填充到指定长度,这样就可以继续对齐了
"build "
>>>s.ljust(2) #少于字符串的话 返回原字符串
"build"
- 打印列表
>>>li=['a','b']
>>>print "\n".join(li) # 一个有用的调试技巧
11,小结
- apihelper.py代码和输出
# 代码
from types import BiultinFunctionType, BulitinMethodType, FunctionType, MethodType, ClassType
def help(object, collapse=1, spacing=10):
""Print methods and doc string.
Take module, class, list, dictionary, or string."""
typeList = (BiultinFunctionType, BulitinMethodType, FunctionType, MethodType, ClassType)
methodList = [method for method in dir(object) if type(getattr(object, emthod)) in typeList]
processFunc = collapse and (lambda s: " ".join(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__
# 输出
>>> from apihelper import help
>>> li = [ ]
>>>help(li)
append L.append(object) -- append object to end
count L.count(value) -> integer -- return number of occurrences of value
extend L.extend(list) -- extend list by appending 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 occurrence of value
reverse L.reverse() -- reverse *IN PLACE*
sort L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
- 自我完成作业
- 选用Import或者from module import导入模块
- 可选和定名参数定义和调用函数
- str强制转换为字符串表达式
- 使用getattr动态函数得到函数和其他的什么引用
- 扩展映射列表进行列表过滤
- and-or的技巧的应用
- 定义lambda函数
- 将函数赋值给变量,然后通过引用变量调用函数。这种思考方式会提高对python的理解力???
可通过本人转载的“Django实战系列”进行django的进一步学习;另外,实战系列的源代码下载地址:在实战系列文章中留言写下邮箱地址,一天内会发送给你全部源代码。 |
|