python学习笔记之函数

在了解了python的基本数据类型后,现在我们来看一下python中的函数,为了便于维护和更好的实现模块化,程序都会分解为多个函数。下面我将总结一下python函数的特性,装饰器,生成器,协程等,他们都是进行函数编程和数据处理的强大工具。

1.函数的定义

在python中定义函数很简单,使用def关键字。和c++一样python的函数也可以使用默认参数。

 

  1. def add(x, y=1):
  2. return x + y
  3. >>> add(1)
  4. 2

python也可以接收任意数量的参数,在最后一个变量前面加星号,python就会把剩下的变量作为元组放入这个变量。

  1. def add(x, y=1, *args):
  2. for i in args:
  3. x += i
  4. return x + y
  5. >>> add(1,2,3,4,5)
  6. 15

上面传递的参数都是根据参数的位置赋值给相应的变量,称为位置参数;python还支持显式地参数赋值,称为关键字参数。

  1. def add(x, y, z, w):
  2. print x,y,z,w
  3. >>> add(1, z=2, w=3, y=4)
  4. 1 4 2 3

注意事项:

  1. 关键字参数的顺序无关紧要。
  2. 位置参数和关键字参数可以一起使用,但关键字参数必须在位置参数后面
  3. 位置参数已经赋值的变量不能再使用关键字参数赋值,比如上面的x已经赋值为1了,后面的关键字参数就不可以再对x赋值。

参数前一个星号表示任意数量的位置参数,两个星号就是任意数量的关键字参数。python会把剩下的关键字参数作为字典放入这个变量。

  1. def foo(*args, **kwargs):
  2. print args,kwargs
  3. >>> foo(1, 2, 3, 4, x=5, y=6)
  4. (1, 2, 3, 4) {'y': 6, 'x': 5}

 

2.装饰器

装饰器是一个函数,主要用于包装另一个函数或类,以修改或增强这个函数或类的行为。装饰器使用@符号表示。

 

  1. def trace(func):
  2. print 'trace'
  3. return func
  4. @trace
  5. def foo():
  6. print 'foo'
  7. foo()
  8. #输出
  9. trace
  10. foo

第一个函数trace()是装饰器函数,他接收一个函数对象func,并返回函数对象(必须返回,但不一定是func),@trace对函数foo()进行修饰,等价于foo = trace(foo),所以最后调用的foo并不是之前定义的foo(),而是trace(foo)。这个例子是在函数foo调用前做一些修饰,也可以在调用前后做一些事情。

  1. # 修改trace
  2. def trace(func):
  3. print 'trace'
  4. def newFunc():
  5. print 'begin'
  6. func()
  7. print 'end'
  8. return newFunc
  9. # 运行foo后输出
  10. trace
  11. begin
  12. foo
  13. end

装饰器是函数,当然也可以接收参数。这样的话必须在装饰器函数内部再定义一个新装饰器函数来接收func对象。

  1. def trace(msg):
  2. print 'trace'
  3. print msg
  4. def newTrace(func):
  5. def newFunc():
  6. print 'begin'
  7. func()
  8. print 'end'
  9. return newFunc
  10. return newTrace
  11. @trace('message')
  12. def foo():
  13. print 'foo'
  14. foo()
  15. # 输出
  16. trace
  17. message
  18. begin
  19. foo
  20. end

 

3.生成器

生成器是一个函数,他生成一个值的序列,用于迭代。生成器使用yield关键字定义。

 

  1. >>> def countdown(n):
  2. while n>0:
  3. yield n
  4. n -=1
  5. >>> c = countdown(5)
  6. >>> c.next()
  7. 5
  8. >>> next(c)
  9. 4
  10. >>> for i in c:
  11. print i
  12. 3 2 1

上面的c就是一个生成器对象,他可以进行迭代来历遍,在countdown函数内遇到yield就会中止并返回n,直到下次调用next。

3.1.生成器表达式

生成器表达式可以生产一个简单的生成器对象。他和for循环类似,使用圆括号,语法为:
(expression for item in iterable if condition) 后面的if可以省略。

 

  1. >>> a = (2*x for x in xrange(20) if x%3 == 0)
  2. >>> for i in a:
  3. print i
  4. 0 6 12 18 24 30 36

 

3.2.列表推导表达式

这里再说一下列表推导表达式,他的语法和生成器表达式差不多,使用中括号,他将生产一个新的列表,语法为:
[expression for item in iterable if condition] if同样可以省略

 

  1. >>> [2*x for x in xrange(20) if x%3 == 0]
  2. [0, 6, 12, 18, 24, 30, 36]

 

4.协程

协程与生成器类似,只不过他是接收数据,而生成器是输出数据。同样使用yield关键字,作为右值。

 

  1. >>> def receiver():
  2. while True:
  3. x = (yield)
  4. print 'Got ',x
  5. >>> r = receiver()
  6. >>> r.next()
  7. >>> r.send(12)
  8. Got 12
  9. >>> r.send('wuyuans.com')
  10. Got wuyuans.com

协程在使用时必须先next,让程序运行到yield关键字。这时我们可以给他加个装饰器,让他自动运行一次next。

    1. def coroutine(func):
    2. def start(*args, **kwargs):
    3. g = func(*args, **kwargs)
    4. g.next()
    5. return g
    6. return start
    7. @coroutine
    8. def receiver():
    9. while True:
    10. x = (yield)
    11. print 'Got ',x
    12. r = receiver()
    13. r.send(12)
    14. # 输出
    15. Got 12
posted @ 2017-07-28 18:46  天涯海角路  阅读(166)  评论(0)    收藏  举报