第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. js添加、删除Cookie

    //cookie function addCookie(objName, objValue, objHours) { //添加cookie var str = objName + "=&qu ...

  2. 【剑指offer】连续子数组的最大和

    个開始,到第3个为止).你会不会被他忽悠住? 输入: 输入有多组数据,每组測试数据包括两行. 第一行为一个整数n(0<=n<=100000),当n=0时,输入结束.接下去的一行包括n个整数 ...

  3. js 推断 当页面无法回退时(history.go(-1)),关闭网页

    在做一个Web项目时遇到一个需求,当页面没有前驱历史记录时(就是当前为新弹出的页面,没法做goback操作即history.go(-1)),点击返回button时直接关闭页面,否则就退回到前一页. 遇 ...

  4. ios5和ios6横竖屏支持及ipad和iphone设备的判断

    ios5和ios6横竖屏支持及ipad和iphone设备的判断 判断是ipad还是iphone设备.此定义在PayViewControllerDemo-Prefix.pch 定义如下: #define ...

  5. 基于zepto的手机焦点图touchstart touchmove

    基于zepto的手机焦点图,查看地址:demo (建议使用手机浏览器查看)代码如下: <!DOCTYPE HTML> <html> <head> <title ...

  6. asp.net文件下载

    protected void btn_Down(object sender, EventArgs e) { string filePath = Server.MapPath("/TradeL ...

  7. WCF Test Client

    WCF测试客户端(WCF Test Client)是一个用来测试WCF服务程序的调试工具,能够使开发WCF服务更加方便. 在Visual Studio之外打开WCF测试客户端有两种方法:第一种方法是到 ...

  8. 【转】这些隐藏在苹果iPhone当中的内置代码你是否知道?

    原文地址:http://www.ithome.com/html/iphone/200569.htm 每一部手机都有一些内置的隐藏代码,我们称之为“指令”,这些代码加在一起就叫做“指令集”.当然这些代码 ...

  9. JVM ClassLoader加载过程

    虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是Java虚拟机的类加载机制. 1)三个类加载器: bootstra ...

  10. CxImage整理(叠加字符/图像合并)

    //CxImage叠加字符 void CCxImageTestDlg::OnBnClickedButton1() { CxImage imgJPG; // 定义一个CxImage对象 imgJPG.L ...