第11章 函数和函数式编程

一 调用函数

 1 关键字参数

  def foo(x):
    foo_suite # presumably does some processing with 'x'

  标准调用 foo():  foo(42)  foo('bar')  foo(y)

  关键字调用 foo():  foo(x=42)  foo(x='bar')  foo(x=y) 即明确给出相应的参数名

2 参数组

  Python允许程序员执行一个没有显式定义参数的函数,相应的方法是通过一个把元组(非关键字参数)或字典(关键字参数)作为参数组传递给函数。

  func( *tuple_grp_nonkw_args, **dict_grp_kw_args )

3 小结

  python 中允许的函数调用的完整语法为:
    func( positional_args, keyword_args, *tuple_grp_nonkw_args, **dict_grp_kw_args )

二 创建函数

1 def语句

  def function_name(arguments):
    "function_documentation_string"
    function_body_suite

  特别注意:python不区分函数的声明与定义!

2 函数属性

  函数也可以有用.号表示的属性

3 内部函数

  在函数体内创建另外一个函数:

  def foo():

    def bar():

      print 'bar() called'

    bar()   #bar()属于函数foo的内部函数,因此只能在foo函数体内部进行调用!!!

4 传递函数

  python的函数和普通对象一样,可以被传递

  举例:

    >>> def foo():
    ... print 'in foo()'
    ...
    >>> bar = foo  函数传递!
    >>> bar()
    in foo()

  

    >>> def bar(argfunc):
    ... argfunc()
    ...
    >>> bar(foo)  函数传递!
    in foo()

三 函数参数

1 形式参数

  (1)位置参数:  必须以在被调用函数中定义的准确顺序来传递

  (2)默认参数

2 可变长度参数

  (1)非关键字可变参数(元组)

      def function_name([formal_args,] *vargs_tuple):  #所有形式参数必须先于非正式的参数之前出现!!!
        "function_documentation_string"
        function_body_suite

      举例:

      def tupleVarArgs(arg1, arg2='defaultB', *theRest):  

        print 'formal arg 1:', arg1

        print 'formal arg 2:', arg2

        for eachXtrArg in theRest:

          print  'another arg:', eachXtrArg

      

      >>> tupleVarArgs('abc', 123, 'xyz', 456.789)
      formal arg 1: abc
      formal arg 2: 123
      another arg: xyz
      another arg: 456.789

  (2)关键字变量参数(字典)

     def function_name([formal_args,][*vargst,] **vargsd):
       function_documentation_string function_body_suite

     举例:

      def dictVarArgs(arg1, arg2='defaultB', **theRest):

        print 'formal arg1:', arg1
        print 'formal arg2:', arg2
        for eachXtrArg in theRest.keys():
          print 'Xtra arg %s: %s' % \
          (eachXtrArg, str(theRest[eachXtrArg]))

      

      >>> dictVarArgs('one', d=10, e='zoo', men=('freud', 'gaudi'))

      formal arg1: one

      formal arg2: defaultB

      Xtra arg men: ('freud', 'gaudi')

      Xtra arg d: 10

      Xtra arg e: zoo

   (3)关键字和非关键字可变长参数同时出现的情形

      要求:关键字字典是最后一个参数并 且非关键字元组先于它之前出现

      def newfoo(arg1, arg2, *nkw, **kw):
        print 'arg1 is:', arg1

        print 'arg2 is:', arg2

        for eachNKW in nkw:
          print 'additional non-keyword arg:', eachNKW
        for eachKW in kw.keys():
          print "additional keyword arg '%s': %s" % \
          (eachKW, kw[eachKW])

      >>> newfoo('wolf', 3, 'projects', freud=90, gamble=96)

      arg1 is: wolf arg2 is: 3
      additional non-keyword arg: projects
      additional keyword arg 'freud': 90
      additional keyword arg 'gamble': 96

   (4)更多举例

      >>> newfoo(2, 4, *(6, 8), **{'foo': 10, 'bar': 12})
      arg1 is: 2
      arg2 is: 4
      additional non-keyword arg: 6
      additional non-keyword arg: 8
      additional keyword arg 'foo': 10
      additional keyword arg 'bar': 12

      >>> aTuple = (6, 7, 8)
      >>> aDict = {'z': 9}
      >>> newfoo(1, 2, 3, x=4, y=5, *aTuple, **aDict)
      arg1 is: 1
      arg2 is: 2
      additional non-keyword arg: 3
      additional non-keyword arg: 6
      additional non-keyword arg: 7
      additional non-keyword arg: 8
      additional keyword arg 'z': 9
      additional keyword arg 'x': 4
      additional keyword arg 'y': 5

四 函数式编程

1 匿名函数与lambda

  python 允许用 lambda 关键字创造匿名函数。匿名是因为不需要以标准的def方式来声明。

  lambda [arg1[, arg2, ... argN]]: expression

  举例:

    def add(x, y): return x + y          等价于   lambda x, y: x + y

    def usuallyAdd2(x, y=2): return x+y    等价于   lambda x, y=2: x+y

    def showAllAsTuple(*z): return z     等价于   lambda *z: z

    >>>a = lambda x, y=2: x + y

    >>>a(3)
    5

    >>>b = lambda *z: z
    >>> b(23, 'zyx')
    (23, 'zyx')
    >>> b(42)
    (42,)

2 内建函数apply()、filter()、map()、reduce()

  lambda 函数可以很好的和这使用了这四个函数的应用程序结合起来,因为它们都带了一个可执行的函数对象,lambda 表达式提供了迅速创造这些函数的机制

  apply( func[, nkw][, kw] )  用可选的参数来调用 func,nkw 为非关键字参数,kw 关键字参数;返回值是函数调用的返回值。

  filter( func, seq) 调用一个布尔函数 func 来迭代遍历每个 seq 中的元素; 返回一个 使 func 返回值为 ture 的元素的序列。

  map( func, seq1[,seq2...] ) 将函数 func 作用于给定序列(s)的每个元素,并用一个列表来提供返回值;如果 func为None,func 表现为一个身份函数,返回一个含有每个序列中元素集合的 n 个元组的列表。

  reduce( func, seq[, init] ) 将二元函数作用于 seq 序列的元素,每次携带一对(先前的结果 以及下一个序列元素),连续的将现有的结果和下雨给值作用在获 得的随后的结果上,最后减少我们的序列为一个单一的返回值;如 果初始值 init 给定,第一个比较会是 init 和第一个序列元素而不 是序列的头两个元素。

  

  举例:

    filter()

      from random import randint

      def odd(n):
        return n % 2
      allNums = []
      for eachNum in range(9):
        allNums.append(randint(1, 99))
      print filter( odd, allNums )

      改变1:用一个 lambda 表达式替换

      from random import randint

      allNums = []
      for eachNum in range(9):
        allNums.append(randint(1, 99))
      print filter( lambda n: n%2, allNums )  #使用了lambda表达式!!!

      

      改变2:list 综合使用如何能成为 filter()合适的替代者

      from random import randint
      allNums = []
      for eachNum in range(9):
        allNums.append(randint(1, 99))
      print [n for n in allNums if n%2]

      改变3:利用列表解析!

      from random import randint as ri
      print [n for n in [ri(1,99) for i in range(9)] if n%2]

    map():

      map( (lambda x: x+2), [0, 1, 2, 3, 4, 5] )

      

      带有多个序列的map()的例子:

      >>> map( lambda x, y: x + y, [1,3,5], [2,4,6])
      [3, 7, 11]
      >>>
      >>> map( lambda x, y: (x+y, x-y), [1,3,5], [2,4,6] )
      [(3, -1), (7, -1), (11, -1)]
      >>>
      >>> map( None, [1,3,5], [2,4,6] )
      [(1, 2), (3, 4), (5, 6)]

    reduce():

      >>> print 'the total is:', reduce( (lambda x,y: x+y), range(5) )
      the total is: 10  #0+1+2+3+4=10

3 偏函数应用(PFA)

  这种函数将任意数量(顺序)的参数的函数转化成另一个带剩余参数的函数对象

  例子:

    >>> from operator import add, mul
    >>> from functools import partial
    >>> add1 = partial(add, 1)         # add1(x) == add(1, x)
    >>> mul100 = partial(mul, 100)     # mul100(x) == mul(100, x)
    >>>
    >>> add1(1)
    2
    >>> mul100(10)
    1000

    >>> baseTwo = partial(int, base=2)
    >>> baseTwo.__doc__ = 'Convert base 2 string to an int.'
    >>> baseTwo('10010')
    18
    这个例子使用了 int()内建函数并将 base 固定为2来指定二进制字符串转化。现在没有多次用相同的第二参数2来调用int (), 比如('10010', 2),而可以只用带一个参数的新 baseTwo()函数。

    注意警惕关键字:

    这个例子如果你创建了不带 base 关键字的偏函数,比如, baseTwoBAD = partial(int, 2),这可能 会让参数以错误的顺序传入 int(),因为固定参数的总是放在运行时刻参数的左边, 比如 baseTwoBAD(x) == int(2, x)。如果你调用它,它会将2作为需要转化的数字,而base 作为'10010' 来传入,然后就产生一个异常:

    >>> baseTwoBAD = partial(int, 2)  #词句和上面的区别就在于没有写base=2
    >>> baseTwoBAD('10010')
    Traceback (most recent call last): File "<stdin>", line 1, in <module>
    TypeError: an integer is required

五 变量作用域

1 全局变量和局部变量

2 globa语句

  为了明确地引用一个已命名的全局变量,须使用global修饰:

   global var1

3 闭包

    若在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是 closure。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量。

  简单闭包的例子:

    def counter(start_at=0):

      count = [start_at]

      def incr():
        count[0] += 1
        return count[0]
      return incr         #注意返回的是一个可调用的函数对象!!!

    >>> count = counter(5)
    >>> print count()
    6
    >>> print count()
    7
    >>> count2 = counter(100)
    >>> print count2()
    101
    >>> print count()
    8

4 作用域和lambda

  python的lambda匿名函数遵循和标准函数一样的作用域规则。一个 lambda 表达式定义了新的作用域。

六 生成器

生成器是一个带 yield语句的函数。一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果----那就是 yield 语句的功能,返回一个值给调用者并暂停执行。当生成器的 next()方法被调用的时候,它会准确地从离开地方继续

简单的生成器特性:

  def simpleGen():
    yield 1
    yield '2 --> punch!'

  >>> myG = simpleGen()
  >>> myG.next()
  1
  >>> myG.next()
  '2 --> punch!'
  >>> myG.next()
  Traceback ( most recent call last ):
  File "", line 1, in ?
  myG.next() StopIteration

  

  from random import randint
  def randGen(aList):
    while len(aList) > 0:
      yield aList.pop( randint(0, len(aList) ) )
  >>> for item in randGen(['rock', 'paper', 'scissors']):
  ...     print item
  ...
  scissors
  rock
  paper

加强的生成器特性:

  在 python2.5 中,一些加强特性加入到生成器中,所以除了next()来获得下个生成的值,用户可以将值回送给生成器,在生成器中抛出异常,以及要求生成器退出:

  def counter(start_at=0):
    count = start_at
    while True:
      val = (yield count)

      if val is not None:
        count = val
      else:
        count += 1

  >>> count = counter(5)
  >>> count.next()
  5
  >>> count.next()
  6
  >>> count.send(9)
  9
  >>> count.next()
  10
  >>> count.close()

Python核心编程读笔 10:函数和函数式编程的更多相关文章

  1. 【7】python核心编程 第十一章-函数和函数式编程

    1.*函数(与方法)装饰器 装饰器背后的主要动机源自python 面向对象编程.装饰器是在函数调用之上的修饰.这些修饰 仅是当声明一个函数或者方法的时候,才会应用的额外调用. 装饰器的语法以@开头,接 ...

  2. python核心编程学习记录之函数与函数式编程

    @func function 意思是func(function) @func(a) function 意思是func(a)这是个函数对象,在去调用function函数 如果要传额外的值,只传值用*tu ...

  3. 跟着ALEX 学python day3集合 文件操作 函数和函数式编程 内置函数

    声明 : 文档内容学习于 http://www.cnblogs.com/xiaozhiqi/  一. 集合 集合是一个无序的,不重复的数据组合,主要作用如下 1.去重 把一个列表变成集合 ,就自动去重 ...

  4. Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数

    Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...

  5. python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程

    python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...

  6. python学习-day16:函数作用域、匿名函数、函数式编程、map、filter、reduce函数、内置函数r

    一.作用域 作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变 二.匿名函数 lambda:正常和其他函数进行配合使用.正常无需把匿名函数赋值给一个变量. f=lambda x:x*x p ...

  7. day16_函数作用域_匿名函数_函数式编程_map_reduce_filter_(部分)内置函数

    20180729    补充部分代码 20180727    上传代码 #!/usr/bin/env python # -*- coding:utf-8 -*- # ***************** ...

  8. 函数与函数式编程(生成器 && 列表解析 && map函数 && filter函数)-(四)

    在学习python的过程中,无意中看到了函数式编程.在了解的过程中,明白了函数与函数式的区别,函数式编程的几种方式. 函数定义:函数是逻辑结构化和过程化的一种编程方法. 过程定义:过程就是简单特殊没有 ...

  9. day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

随机推荐

  1. UMeditor 百度编辑器Mini学习

    准备开始研究百度的mini编辑器 1.4.3的昨天配置好了 ,也可以用了(.net 3.5) 为此我废了好大的力 研究了一天才弄好   结果今天一来上司就说 这个1.4.3 我们没必要用这么大的  用 ...

  2. CSS文字超出div或者span时显示省略号

    我们常常需要在文本过长时显示,将超出显示成省略号: 思想为: 首先设置宽度,然后让超出的部分隐藏如果有超出则在最后显示省略号让文本不换行 具体css代码为: .title{ width:200px;o ...

  3. 浏览器的重绘(repaints)与重排(reflows)

    转:http://www.css88.com/archives/4991#more-4991 在项目的交互或视觉评审中,前端同学常常会对一些交互效果质疑,提出这样做不好那样做不好.主要原因是这些效果通 ...

  4. Http权威指南笔记(一) URI URL URN 关系

    定义 URI:统一资源标识符(Uniform Resource Indentifier)用来标识服务器上的资源. URL:统一资源定位符(Uniform Resouce Locator)是资源标识符最 ...

  5. c++到c#数据类型的转换

    c++与c#的类型转换 分类:cSharp | 标签: c#  system  intptr  char  uint  2012-02-29 19:54 阅读(513)评论(0)编辑删除 //c++: ...

  6. zoj1074 To the Max

    题目很简单,求一个连续的最大子矩阵的值. zoj上的数据非常弱. 首先爆搜是O(N^4),10^8的复杂度略高,那么我们可以处理一下其中一维的前缀和,降一阶,然后按照连续最大子序列来处理,因为可能为负 ...

  7. 关于 zend studio 中有些php 内置函数没有提示,或是有‘小黄色感叹号’

    解决办法: 1.修改项目 .buildpath 文件 <?xml version="1.0" encoding="UTF-8"?> <buil ...

  8. EditText默认不弹出软键盘

    #EditText默认不弹出软键盘# 网上关于EditText默认情况下不弹出软键盘,当手触摸到EditText,获取焦点时候,才会弹出软键盘,貌似都不能用,其实,在oncreate()方法中,加上 ...

  9. C语言基础03

    1.随机数 :一个范围内随机数字的返回值. 格式为: arc4random() % ( num大值 -num小值 + 1 ) + num小值. int n,i= 0;           //控制随机 ...

  10. 【Chromium中文文档】Chrome/Chromium沙箱 - 安全架构设计

    沙箱 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Sandbox.ht ...