四、匿名及递归函数

1、函数设计
  • 耦合性
    • 对于输入是用参数并且对于输出使用return语句;
    • 只有真正必要的情况下使用全局变量;
    • 不要改变可改变类型的参数,除非调用者希望这样;
    • 每个函数都应有一个单一的、统一的目标;
    • 每个函数应相对较小;
    • 避免直接改变在另一个模块文件中的变量。
 总之,使函数和其他编程组件中的外部依赖性最小化。函数的自包含性越好,则越容易被理解、复用和修改。
 
函数执行环境:
 
 
2、递归函数
 
(1)直接或间接地调用自身以进行循环的函数。
  • 定义简单,逻辑清晰;缺点:过深调用会导致栈溢出

(2)通常包含两部分:

  • 基线条件(针对最小的问题):满足这种条件时函数将直接返回一个值。
  • 递归条件:包含一个或多个调用,这个调用旨在解决问题的一部分。

(3)递归定律:

  • 必须有基本结束条件;
  • 必须改变自己的状态并向基本结束条件演进;
  • 必须递归调用自身

(4)需要防止栈溢出

  • 在计算机中,函数调用是通过栈(stack)实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小有限,所以,递归调用的次数过多会导致栈溢出。
  • 解决方法:通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
    • 尾递归:是指在函数返回时,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,是递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环

Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题

 

3、函数对象:属性和注解

  • 与函数的参数和结果相关的任意的用户定义的数据。
  • 是可选的,出现时只附加到函数对象的__annotations__属性以供其他用户使用。
  • 有注解时,Python将它们收集到字典中并且将它们附加给函数对象自身。
  • 编写了注解仍可对参数使用默认值。

注解只在def语句中有效,在lambda表达式中无效。

 

4、匿名函数(lambda)

  • lambda表达式
  • 创建了 一个可以调用的函数;
  • 返回函数而不是将这个函数赋值给一个变量名;
  • 是表达式,而不是一个语句;
  • 主体时一个单个的表达式,而不是一个代码块。
  • 通常用来编写跳转表,即行为的列表或字典,能够按照需要执行相应的动作。

在lambda中打印时使用sys.stdout.write(str(x)+'\n')。

    

 

嵌套lambda和作用域,嵌套的lambda能够获取到在上层函数作用域中的变量名x的值

  

 

5、函数式编程工具

(1)map

    

(2)filter

(3)reduce

接受一个迭代器来处理,自身不是迭代器,返回一个单个的结果。

 

posted @ 2020-05-31 14:51  晨尛  阅读(142)  评论(0编辑  收藏  举报