第十一章,函数
#coding: utf-8
from operator import add,sub
from random import randint, choice
ops={'+':add,'-':sub}
MAXTRIES=2
def doprob():
op=choice('+-')
nums=[randint(1,40) fori in range(2)]
nums.sort(reverse=True)
ans=ops[op](*nums)
pr='%d%s%d='%(nums[0],op,nums
![[1] [1]](http://static.javashuo.com/static/loading.gif)
)
oops=0
while True:
try:
ifint(raw_input(pr))==ans:
print '马思尧correct'
break
ifoops==MAXTRIES:
print'answer\n%s%d'%(pr,ans)
else:
print'马思尧你算错了,incorrect...try again'
oops=oops+1
except(KeyBoardInterrupt,EOFError,ValueError):
print'invalid input... try again'
def main():
while True:
doprob()
try:
opt=raw_input('again?
![[y] [y]](http://static.javashuo.com/static/loading.gif)
').lower()
if opt andopt[0]=='n':
break
except(KeyboardInterrupt,EOFError):
break
if __name__=='__main__':
main()
这个小程序的知识点在ans=ops[op](*nums),把一个列表传递给函数,ops[op]是add()或者sub()函数。
Python 一样容许程序员执行一个没有显式定义参数的函数,相应的方法是经过一个把元组(非关键字
参数)或字典(关键字参数)做为参数组传递给函数。咱们将在本章中讨论这两种形式。基本
上,你能够将全部参数放进一个元组或者字典中,仅仅用这些装有参数的容器来调用一个函数,而
没必要显式地将它们放在函数调用中:func(*tuple_grp_nonkw_args,**dict_grp_kw_args)
闭包的概念:
若是在一个内部函数里,对在外部做用域(但不是在全局做用域)的变量进行引用,那么内部函数就被认为是closure。定义在外部函数内的但由内部
函数引用或者使用的变量被称为自由变量
自由变量 和 函数,这两个关键稍后再说。仍是得在赘述下“闭包”的意思,望文知意,能够形象的把它理解为一个封闭的包裹,这个包裹就是一个
函数,固然还有函数内部对应的逻辑,包裹里面的东西就是自由变量,自由变量能够在随着包裹处处游荡。固然还得有个前提,这个包裹是被建立出
来的。
在经过Python的语言介绍一下,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫作闭包。你在调用函数A
的时候传递的参数就是自由变量。
实例:
def func(name):
definner_func(age):
print 'name:', name, 'age:', age
return inner_func
bb = func('the5fire')
bb(26) # >>> name: the5fire age:26
这里面调用func的时候就产生了一个闭包——inner_func,而且该闭包持有自由变量——name,所以这也意味着,当函数func的生命周期结束以后,
name这个变量依然存在,由于它被闭包引用了,因此不会被回收
2. 为何使用闭包
3. 使用闭包
装饰器,第一次据说这个东西,好好研究一下。
那什么是装饰器?。。。。如今咱们知道装饰器实际就是函数,他们接受函数对象
装饰器的做用:
引入日志
?? 增长计时逻辑来检测性能
?? 给函数加入事务的能力
使用函数装饰器的例子(deco.py)
默认参数和关键字参数的区别,
其实我一直知道默认参数是什么,可是不知道关键字参数是什么。
def func(name,age=1,gender=m):
pass
这个函数里age,gender就是默认参数,调用函数时能够不给age和gender赋值。func('raoxiaoyuan')是正确的
那么关键字参数是什么呢?
#关键字参数
#用上面第一個例子 person( name, age=1, gender='M')
#用关键字給function傳值時,不雖要跟著順序來也沒問題
#就算 age 和 name 順序不一样, 但因為是用关键字來傳值,因此沒問題
person( age=18, name='Jacky')
#output --> name: Jacky age: 18 gender: 'M'
person( gender='F', age=17, name='Ashley')
#output --> name: Ashley age: 17 gender: 'F'
//////////////////////////////////////////////////////
原来关键字参数就是age=18, name='Jacky'这样来赋值就是关键字参数啊,呜呼哀哉。。。
可变长参数有几种:
1.非关键字可变长参数(元组)
def function_name([formal_args,]*vargs_tuple):#*vargs_tuple这个元组收纳全部其余的参数。
"function_documentation_string"
function_body_suite
2..关键字变量参数(Dictionary)(字典)
def function_name([formal_args,][*vargst,] **vargsd):
function_documentation_string function_body_suite
[*vargst,]#*vargst这个元组收纳全部其余的非关键字的参数
**vargsd#关键字变量参数应该为函数定义的最后一个参数,带**
函数式编程的内建函数
apply()已弃用,不作研究
filter():
filter(...)
filter(function or None,sequence) -> list, tuple, or string
说明:
对sequence中的item依次执行function(item),将执行结果为True(!=0)的item组成一个List/String/Tuple(取决于sequence的类型)返
回,False则退出(0),进行过滤。
map():
map(...)
map(function, sequence[,sequence, ...]) -> list
说明:
对sequence中的item依次执行function(item),执行结果输出为list。
reduce():
reduce(...)
reduce(function,sequence[, initial]) -> value
说明:
对sequence中的item顺序迭代调用function,函数必需要有2个参数。要是有第3个参数,则表示初始值,能够继续调用初始值,返回一个值。
应用map,reduce,filter
1):实现5!+4!+3!+2!+1!
code:
def newlist(n):
count=[]
for i in map(lambdax:x+1,range(n)):
m=reduce(lambda x,y:x*y,map(lambdax:x+1,range(i)))
count.append(m)
return count
if __name__=='__main__':
try:
n=input('please input number(int type):')
result=newlist(n)
print reduce(lambda x,y:x+y,result)
except(NameError,TypeError):
print 'that is not a number'
2)将100~200之内的质数挑选出来
code:
def is_prime(start,stop):
stop=stop+1
prime = filter(lambda x: not [x%i for i in range(2,x) if x%i ==0],range(start,stop))
prime = filter(lambda x: not [x%i for i in range(2,x) if x%i ==0],range(start,stop))
print prime
is_prime(100,200)
偏函数应用:什么是偏函数?Currying 能泛化成为偏函数应用(PFA), 这种函数将任意数量(顺
序)的参数的函数转化成另外一个带剩余参数的函数对象。
在某种程度上,这彷佛和不提供参数,就会使用默认参数情形类似。
例子:
变量做用域:
核心笔记:搜索标识符(aka 变量,名字,等等)
当搜索一个标识符的时候,python 先从局部做用域开始搜索。若是在局部做用域内没有找到那
个名字,那么就必定会在全局域找到这个变量不然就会被抛出NameError 异常。
一个变量的做用域和它寄住的名字空间相关。咱们会在12 章正式介绍名字空间;对于如今只能
说子空间仅仅是将名字映射到对象的命名领域,如今使用的变量名字虚拟集合。做用域的概念和用
于找到变量的名字空间搜索顺序相关。当一个函数执行的时候,全部在局部命名空间的名字都在局
部做用域内。那就是当查找一个变量的时候,第一个被搜索的名字空间。若是没有在那找到变量的
话,那么就可能找到同名的全局变量。这些变量存储(搜索)在一个全局以及内建的名字空间,。
仅仅经过建立一个局部变量来“隐藏“或者覆盖一个全局变量是有可能的。回想一下,局部名字空间是首先被搜索的,存在于其局部做用域。若是找
到一个名字,搜索就不会继续去寻找一个全
局域的变量,因此在全局或者内建的名字空间内,能够覆盖任何匹配的名字。
若是函数包含了对其自身的调用,该函数就是递归
生成器?