函数(五)

递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自己本身,那这个函数就是递归函数。

举个例子,我们来计算阶乘n! = 1 * 2 * 3 * ... * n ,用函数fact(n)表示,可以看出:

fact(n) = n! = 1 * 2 * 3 * ... * (n-1) * n = fact(n-1) * n

所以,fact(n)可以表示为fact(n-1)*n,只有当n=1的时候需要特殊处理

于是,fact(n)用递归的方式写出来就是:

def fact(n):
    if n == 1:
        return 1
    return n * fact(n-1)

如果我们计算fact(5),可以看到

--> fact(5)
--> 5 * fact(4)
--> 5 * (4 * fact(3))
--> 5 * (4 * (3 * fact(2)))
--> 5 * (4 * (3 * (2 * fact(1))))
--> 5 * (4 * (3 * (2 * 1)))
--> 5 * (4 * (3 * 2))
--> 5 * (4 * 6)
--> 5 * 24
--> 120

如果递归函数不断地调用函数自身,那么这个递归函数就会进入一个死循环,因此我们应该给递归函数一个明确的结束条件。

递归的核心:递进的时候能够达到一个结果,问题规模越来越小(不一定要真正的达到);设置一个条件后,能够让最后一次函数调用结束。

递归有两个明确的阶段:

  1. 递推:一层一层的调用下去,进入下一层后,问题规模都会减小。
  2. 回溯:递归遇到终止条件后,会从最后往回一级一级的把值返回来。

递归函数有3个特点:

  1. 直接或间接的调用自身
  2. 具有结束条件,防止递归外溢
  3. 代码规模逐渐减少

递归函数的优点是定义简单,逻辑清晰,缺点是过深的调用会导致栈溢出。

理论上,所有的递归函数都可以写成循环的方式,但是循环的逻辑不如递归清晰。

递归就是函数调用函数本身,然后有结束条件。

内置方法

  1. bytes()

    解码字符

res = bytes('你好', encoding='utf8')
print(res)

# b'\xe4\xbd\xa0\xe5\xa5\xbd'
  1. chr()/ord()

    chr()参考ASCII码表将数字转成对应字符;ord()将字符转换成对应的数字。

print(chr(97))

# a
print(ord('a'))

# 97
  1. divmod()

    分栏

print(divmod(10, 3))

# (3, 1)
  1. enumerate()

    带有索引的迭代

lt = ['a', 'b', 'c']
for i in enumerate(lt):
    print(i)

# (0, 'a')
# (1, 'b')
# (2, 'c')
  1. eval()

    把字符串翻译成数据类型

lis = '[1, 2, 3]'
lis_eval = eval(lis)
print(lis_eval)

# [1, 2, 3]
  1. hash()

    是否可哈希

print(hash(1))

# 1

面向过程编程

面向过程编程绝对不是函数编程那么简单,面向过程是一种编程思想,而编程思想是不依赖具体的语法的。即我们不依赖于函数,也可以基于面向过程的思想编写程序。

面向过程编程,过程是解决问题的步骤,即先干什么后干什么

基于面向过程设计的程序,就好比在设计一条流水线,是一种机械式的思维方式

优点:复杂的问题流程化,进而简单化

缺点:功能与功能之间不独立,可扩展性差,牵一发而动全身

posted @ 2019-08-14 16:30  云台三落  阅读(148)  评论(0编辑  收藏  举报