第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. android JNI库实现reboot,recovery

    1.recovery函数: #define UPDATE_TITLE "--update_package=" #define UPDATE_COMMAND_FILE "/ ...

  2. [LeetCode] Search in Rotated Sorted Array [35]

    题目 Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 m ...

  3. C#1 输入输出 常量变量

    C#  输入输出  常量变量 //输出 Console.WriteLine("这是一行文字"); 自动回车的. Console.Write("Hello world&qu ...

  4. spring sts 从数据库中反向生成实体类

    首先我们要在sts中建立mysql的数据库连接 1. 当点击ok之后,如果没有报错的话就应该是建立好了,我们可以点击查看这个数据库中所有的表 我们就可以再sts进行数据库操作了,具体如下: 点击如下按 ...

  5. android中viewPager实现的屏幕左右切换(入门篇)

    大多数的APP都可以实现几个屏幕来回的切换, 首先新建两个Activity,内容随意,布局随意.接下来在MainActivity.xml: <RelativeLayout xmlns:andro ...

  6. Android Fragment真正意义上的onResume和onPause

    Fragment虽然有onResume和onPause的,但是这两个方法是Activity的方法,调用时机也是与Activity相同,和ViewPager搭配使用这个方法就很鸡肋了,根本不是你想要的效 ...

  7. Javascript 拖拽的一些高级的应用——逐行分析代码,让你轻松了解拖拽的原理

    我们看看之前的拖拽在周围有东西的时候会出现什么问题? 在高级浏览器中不会有啥问题,我们放到IE7下面测试一下,问题就出来了.如图 我们可以很清楚的看到,文字都已经被选中了.那这个用户体验很不好,用起来 ...

  8. (极简)linux安装QT4.7.3

    1.下载QT http://download.qt.io/ 我用的:qt-everywhere-opensource-src-4.7.3.tar.gz 2.解压安装QT 建议解压到/use/local ...

  9. 数据结构-B树

      1.前言: 动态查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced Binary Search Tree),红黑树(Red-Black Tree ) ...

  10. Oracle EBS-SQL (WIP-11):检查期间任务完工记录数.sql

    select        WE.WIP_ENTITY_NAME                 任务名称,        WDJ.class_code                         ...