1.函数的嵌套定义:在函数里面定义一个函数。
2.装饰器:装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。装饰器的作用就是为已经存在的对象添加额外的功能。其实总体说起来,装饰器其实也就是一个函数,一个用来包装函数的函数,返回一个修改之后的函数对象,将其重新赋值原来的标识符,并永久丧失对原始函数对象的访问
#!/usr/bin/env python import time import datetime def func(fc): print "haha" def wrap(*arg,**kwargs): start =datetime.datetime.now() fc(*arg,**kwargs) end =datetime.datetime.now() //计算函数运行时间 cost = end-start print cost.total_seconds() //输出运行时间 return wrap @func //装饰器的调用 def f1(arg1): print arg1 time.sleep(2) def f2(): print "666" #f = func(f1) f1(arg1=100)
@func作为装饰器函数,该装饰器的作用相当于:f1=func(f1),但是,注意在使用装饰器函数时,所需要装饰的函数必须要紧跟在该函数后
本质上,decorator装饰函数就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:
def log(func): def wrapper(*args, **kw): print 'call %s():' % func.__name__ return func(*args, **kw) return wrapper
观察上面的log
,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:
@logdef now(): print '2013-12-25'
调用now()
函数,不仅会运行now()
函数本身,还会在运行now()
函数前打印一行日志:
>>> now()call now():2013-12-25
把@log
放到now()
函数的定义处,相当于执行了语句:
now = log(now)
由于log()
是一个decorator,返回一个函数,所以,原来的now()
函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()
将执行新函数,即在log()
函数中返回的wrapper()
函数。
wrapper()
函数的参数定义是(*args, **kw)
,因此,wrapper()
函数可以接受任意参数的调用。在wrapper()
函数内,首先打印日志,再紧接着调用原始函数。
3.匿名函数:lambda定义匿名函数。声明方式不一样,调用方式是一样的
>>> f = lambda *x:map(lambda x:x+10,x)
>>> f(1,2,3)
[11, 12, 13]
>>> f(*[1,2,3,4])
[11, 12, 13, 14]
#!/usr/bin/env python
func = {
"add":lambda x,y: x+y,
"sub":lambda x,y: x-y,
"mul":lambda x,y: x*y,
"div":lambda x,y: x/y,
}
print func["add"](1,2)
4.生成器函数:可以从外面接受哟一个值,再进行计算,把值返回出去。
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
生成器:
保存了当前的状态,需要调用
生成器生成的就是个迭代器。
>>> gen = (x+2 for x in range(5))
>>> gen
<generator object <genexpr> at 0x7f7817e50dc0>
>>> gen.next()
2
>>> gen.next()
3 //前面的不见了因为用完next后,游标移动到下一位。
>>> for i in gen:
... print i
...
4
5
6
(一般来说出现yield的函数是生成器函数)
——————————————————————————————————————————
def odd():
alue >=10:
break
n = 1
while True:
yield n // 中断(交出CPU),保存当前信息。返回n的值(不打印)
alue >=10:
break
n += 2
o = odd()
o.next() //执行生成器(里面的代码) // print o.nsxt() 打印出来
____________________________________________________________________________________
//既有return又有yield//如果先遇到return 也会中断。
.close 关掉生成器。
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
(####多进程多线程。####awk###rsinc####这些东西可以了解一下!)
send //为什么不用 .next ?因为它不可以传值进去。
#!/usr/bine/env python
def gen():
val = 0
while True:
recv=yield val //recv接受值,yield返回值。
if recv == 'e':
break
elif recv == 'haha':
val = 'hehe'
elif recv == 'byebye':
val = 'gun!'
else:
val = '?????'
g = gen()
g.send(None) ///send有隐饰的next的含义,当为None的时候,不往下执行
while True:
text = raw_input("ples input:")
if text == 'e':
print "3q"
break
print g.send(text) //打印出传第的值
generator是非常强大的工具,在Python中,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。
要理解generator的工作原理,它是在for
循环的过程中不断计算出下一个元素,并在适当的条件结束for
循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for
循环随之结束。