跟老齐学Python之传说中的函数编写条规(2)
还记得,在第一部分学习的时候,不断强调的:变量无类型,数据有类型,那时候遇到的数据包括字符串、数值、列表、元组、字典、文件,这些东西,都被视为对象。函数跟它们类似,也是对象。因此就可以像以前的对象一样进行赋值、传递给其它函数、嵌入到数据结构、从一个函数返回给另一个函数等等面向对象的操作。当然,函数这个对象也有特殊性,就是它可以由一个函数表达式后面的括号中的列表参数调用。
>>> def newsum(lst): #依然以这个递归的函数为例
... print lst
... if not lst:
... return 0
... else:
... return lst[0] + newsum(lst[1:])
...
>>> lst = [1,2,3]
>>> newsum(lst) #这是前面已经常用的方法
[1, 2, 3]
[2, 3]
[3]
[]
6
>>> recusion_fun = newsum #通过赋值语句,让变量recusion_fun也引用了函数newsum(lst)对象
>>> recusion_fun(lst) #从而变量能够实现等同函数调用的操作
[1, 2, 3]
[2, 3]
[3]
[]
6
再看一个例子,在这个例子中,一定要谨记函数是对象。看官曾记否?在list中,可以容纳任何对象,那么,是否能够容纳一个函数中呢?
>>> fun_list = [(newsum,[1,2,3]),(newsum,[1,2,3,4,5])]
>>> for fun,arg in fun_list:
... fun(arg)
...
[1, 2, 3]
[2, 3]
[3]
[]
6
[1, 2, 3, 4, 5]
[2, 3, 4, 5]
[3, 4, 5]
[4, 5]
[5]
[]
15
函数,真的就是对象啊。
既然是对象,就可以用dir(object)方式查看有关信息喽:
>>> dir(newsum)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> dir(newsum.__code__)
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
>>> newsum.__code__.__doc__
'code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\nCreate a code object. Not for the faint of heart.'
>>> newsum.__code__.co_varnames
('lst',)
>>> newsum.__code__.co_argcount
1
所以,各位看官,在使用函数的时候,首先要把它放在对象的层面考量,它不是什么特殊的东西,尽管我们使用了不少篇幅讲述它,但它终归还是一个对象。