知乎:https://www.zhihu.com/people/monkey.d.luffy Android高级开发交流群2: 752871516
全部博文(315)
分类: Python/Ruby
2012-02-22 21:33:57
过年了,看书都没有什么状态,感觉很嘈杂!希望在新的一年里,大家都可以事事如意,没事出去散散心,释放自己的烦恼,只有自己快乐,家人健康,朋友幸福才是王道!
第11章是关于函数的,讲的不浅哦。尤其是装饰器那块,我现在还有一个例子没有调试出来。只有慢慢来了,估计是自己没有怎么理解,所以就先搁着,懂了再说。后面敲一个函数式编程的例子:(写下注释,这章都没写多少东西,其实很多都要自己去理解和深入)
11.1 函数式编程举例
# file: testit.py
#!/usr/bin/env python
#该函数传入了一个函数对象(其实只是一个元组的元素,不过是函数名,就像c语言的函数指针),两个参数;
#一个带一个*: 表示非关键字可变长参数(元组)
#一个带两个*: 表示关键字变长参数(字典)
#注意:如果同时出现两种变长参数,要保证关键字变长参数作为最后一个参数,并且非关键字参数出现在它之前就可以
def testit(func, *nkwargs, **kwargs):
try:
retval = func(*nkwargs, **kwargs)
result = (True, retval)
except Exception, diag:
result = (False, str(diag)) #一个元组,两个参数;布尔值和异常字符串
return result
def test():
funcs = (int, long, float)
vals = (1234, 12.34, '1234', '12.34')
for eachFunc in funcs:
print '-' * 20
for eachVal in vals:
retval = testit(eachFunc, eachVal) #testit传入eachFunc---假设是int, 传入eachVal---假设是1234;这样进入testit函数执行,你就明白了
if retval[0]:
print '%s(%s) =' % \
(eachFunc.__name__, `eachVal`), retval[1] #这里加``的意义是可以保持像’1234’,’12.34’这样字符串保持本来的显示模式,不然直接eachVal的话,显示时’1234’会变成1234这样去显示;
else:
print '%s(%s) = FAILED:' % \
(eachFunc.__name__, `eachVal`), retval[1]
if __name__ == "__main__":
test()
11.2 lambda关键字的意义
Lambda表达式返回一个可调用的函数对象至于具体叫什么名字就不知道了,如果要很深入了解的话,估计要去研究lambda的工作机制了。这里我们只是简单的了解下基础知识,能看懂几个小例子就可以了。
Lambda是单行操作,大大简化你的代码,而且节省内存空间,因为它不会开辟函数栈帧,因此你必须用一个变量来接收它的返回值,不然你直接运用它,结果是看不到的。但是用变量接收后,然后执行变量() 就能看到结果了;这样我们就可以把lambda表达式赋值给一个列表啊,元组之类的;以下是课本的例子:
def add(x, y) : return x + y ? lambda x, y : x + y #lambda定义了匿名函数,参数是x, y,执行的操作是x + y
11.3 体现函数式编程的内建函数(apply(), filter(),map(),reduce()最难)
apply()就不说了;
filter(): 以下是工作机制(模拟)
#file: myfilter.py
#!/usr/bin/env python
def filter(bool_func, seq):
filtered_seq = [] #list defination
for eachItem in seq:
if bool_func(eachItem):
filtered_seq.append(eachItem)
return filtered_seq
def foo(item):
if item == 2:
return True
else:
return False
if __name__ == "__main__":
myseq = (1, 2, '3', 3.4)
print filter(foo, myseq)
fileter()的运用:
#file: filter.py
#!/usr/bin/env python
from random import randint
def odd(n):
return n % 2
allNums = []
for eachNum in range(9): #create 9 count data;
allNums.append(randint(1, 99))
if __name__ == "__main__":
print filter(odd, allNums)
print filter(lambda n: n%2, allNums) #利用lambda改造
print [n for n in allNums if n%2] #利用列表改进
print [n for n in [randint(1, 99) for i in range(9)] if n%2] #利用列表解析优化
reduce()用法;但是对于高级的估计就不懂了,只是了解下简单的用法,我想肯定没那么简单了。
print ‘the total is:’ reduce((lambda x, y: x + y), range(5)) #还是好理解, reduce以此迭代,最终返回一个结果.
至于‘偏函数’? 偏函数的设计,我认为就是为了把纷繁的诸多参数(当然有默认参数或者没有)的函数通过partial函数来‘分解’,最后返回的函数对象可以减少到一个参数就可以实现计算,像:baseTwo = partial(int, base = 2)
baseTwo(‘1000’)
我们可以封装实现自己的定义函数;这样显得方便多了!至于更高级的应用,以后有机会学到的。注意???文中提到了‘警惕关键字’,其实就是注意,如果你要用库函数来封装自己的函数,那么关键字参数要注意位置,即使是默认参数的函数,如果你写入了base = 2这样的带关键字的默认参数,那么就不会出错了,但是如果你写个2,而且第2参数的位置成为第1参数位置,那么编译器如何能识别了,是吧??
那么你在给函数传递参数时要注意了;还有个解释就是关键字参数始终在形参之后。
后面是一个和偏函数有点关系的gui界面,终于到了TKinter了,但是很遗憾我的电脑没装,而且回家了上不了网,以后补上;简单事例:(还是好理解的)
#file: ppFaGUI_TKinter.py
#!/usr/bin/env python
import TKinter #后来装上python-tk后,测试了下;这里需要将TKinter改为Tkinter;下面的都要改;
from functools
import partial #顺便我安装了下python-dev,好像记得跟网络有关??
root = TKinter.Tk()
MyButton = partial(TKinter.Button, root, fg = 'white', bg = 'blue')
b1= MyButton(text = 'Button1')
b2= MyButton(text = 'Button2')
qb = MyButton(text = 'Quit', bg = 'red', command = root.quit)
b1.pack()
b2.pack()
qb.pack(fill = TKinter.X, expand = True)
root.title('PFAs!')
root.mainloop()
11.4 变量作用域
由于学习了还是比较久的c,所以就扫了一遍;里面还有些概念要提下,就是为什么局部变量可以覆盖全局变量,而且你同时申明或者加定义一个变量在函数内和全局范围,也不会出错。这是因为编译器在扫描你的代码的时候,首先扫描局部变量,如果发现局部变量有了,那么就不再搜索全局是否有这样名字的变量,所以即使全局定义了也不会报错。最后那个无用的变量就会废弃掉,不会分配在.bss段或者数据段----c概念。
后面还有递归,生成器,闭包(说道闭包,想到编译原理的内容,什么聚簇,闭包啊,烦死了,难懂反正,只有慢慢了解)相关的概念,当然变量作用域将的不少,而且很多挺深的!看了学习没那么简单了………..
12. 下一章我就想看下算了。不过里面提到了编码编程,我原来练习的代码里面不可以加入中文,是因为python默认没有支持这种编码格式,所以需要我们自己指定了:
# -*- coding: UTF-8 -*-
加入这样一句就可以支持中文了,其实多练习因为也不错;第12章就是主要讲解模块,我看的快,很多地方不太明白,以前在将arm的时候提到驱动模块啊之类的感觉自己好像明白是那么回事,但是要仔细搞懂它的深刻理论加实践也不是那么简单的,我都看的萌了。不过还是知道如何使用自己的模块了:
文件:testit.py #把它作为模块
方法:首先要将该模块拷贝到python模块相同的路径,或者修改环境变量;
交互模式下:import sys
sys.path #查看有python哪些环境变量
sys.path.append(‘
使用就和平时导入模块,在用句点属性标识法来访问;或者用from …import 来导入的话就可以直接使用函数;这是因为命名空间的缘故,具体命名空间还是挺深的,值得探究,c++里面强调多!