11章 函数/函数式编程

1.函数

  在python中,函数通过def关键字、函数名和可选的参数列表定义。通过return关键字返回值。

2.函数参数

  在Python中函数的参数可以是必须的位置参数或者是关键字参数(默认参数)

>>> def foo(x, y = 1):
	return x-y

>>> foo(3,2)
1
>>> foo(3)
2
>>> 

 3 传递函数

  所以对象都是通过引用来传递,函数也不例外,当对一个变量赋值时,实际是将相同对象的引用赋值给这个变量,如果对象是函数的话,这个对象所有的别名都是可以调用。

>>> def foo():
	print 'in foo()'

	
>>> foo()
in foo()
>>> bar = foo
>>> bar()
in foo()

 foo()函数对象的调用, foo函数对象的引用

4 嵌套函数

  Python允许创建嵌套函数。。

def outer():
     x = 1
     def inner():
         print x # 1
     inner() # 2
 
outer()
1

 python解释器需找一个叫x的本地变量,查找失败之后会继续在上层的作用域里面寻找,这个上层的作用域定义在另外一个函数里面。对函数outer来说,变量x是一个本地变量,函数inner可以访问封闭的作用域,调用函数inner,inner也仅仅是一个遵循python变量解析规则的变量名,Python解释器会优先在outer的作用域里面对变量名inner查找匹配的变量.

5.闭包

该处摘自 "http://python.jobbole.com/81683/" 对闭包解释很到位

>>> def outer():
	x = 1
	def inner():
	    print x #1
	return inner

>>> foo = outer()
>>> foo.func_closure
(<cell at 0x01BB5F30: int object at 0x012D7D20>,)
>>> foo
<function inner at 0x01BB8DF0>
>>> foo()
1

 python的作用域规则下:x是函数outer里的一个局部变量。当函数inner在#1处打印x的时候,python解释器会在inner内部查找相应的变量,当然会找不到,所以接着会到封闭作用域里面查找,并且会找到匹配。

但是从变量的生存周期来看,我们的变量x是函数outer的一个本地变量,这意味着只有当函数outer正在运行的时候才会存在。根据我们已知的python运行模式,我们没法在函数outer返回之后继续调用函数inner,在函数inner被调用的时候,变量x早已不复存在,可能会发生 一个运行时错误。但万万没想到,返回的函数inner居然能够正常工作。Python支持一个叫做函数闭包的特性,用人话来讲就是,嵌套定义在非全局作用域里面的函数 能够记住它在被定义的时候它所处的封闭命名空间。这能够通过查看函数的func_closure属性得出结论,这个属性里面包含封闭作用域里面的值(只会 包含被捕捉到的值,比如x,如果在outer里面还定义了其他的值,封闭作用域里面是不会有的)。

每次函数outer被调用的时候,函数inner都会被重新定义

 def outer(x):
	def inner():
	    print x
	return inner

>>> a = outer(1)
>>> b = outer(2)
>>> a()
1
>>> b()
2
>>> 

 6 装饰器

装饰器就是闭包的体现,是在函数调用上的修饰

def outer(some_func):
     def inner():
         print "before some_func"
         ret = some_func() # 1
         return ret + 1
     return inner
def foo():
     return 1
decorated = outer(foo) # 2
decorated()
before some_func
2

上面这个装饰器的例子。定义了一个函数outer,它只有一个some_func的参数,在里面定义了一个嵌套的函数inner。 inner会打印一串字符串,然后调用some_func,在#1处得到它的返回值。在outer每次调用的时候some_func的值可能会不一样,但是不管some_func的之如何,最终都会调用它。最后,inner返回some_func() + 1的值,通过调用在#2处存储在变量decorated里面的函数能够看到被打印出来的字符串以及返回值2,而不是期望中调用函数foo得到的返回值1。

装饰器的语法是以@开始,接着是装饰器函数的名字和可选参数。紧跟着装饰器声明的是修饰的函数和装饰器的可选参数。

 def timeTest(func):
    def test():
        start = time.clock()
        func()
        end = time.clock()
        print end-start
    return test

@timeTest
def foo():
    print 'foo()'
foo()

关于装饰器,后续新增一篇详细介绍

原文地址:https://www.cnblogs.com/gcm688/p/5308948.html