python入门笔记15——函数用法和底层分析(3)

函数用法和底层分析

lambda 表达式和匿名函数

  lambda 表达式可以用来声明匿名函数。lambda 函数是一种简单的、在同一行中定义函数的方法。lambda 函数实际生成了一个函数对象。
  lambda 表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。

lambda 表达式的基本语法如下:

lambda arg1,arg2,arg3... : <表达式>

  arg1/arg2/arg3 为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运算结果。

f = lambda a,b,c:a+b+c
print(f)
print(f(1,2,3))
print((lambda a,b,c:a+b+c)(1,2,3))

运行结果

<function <lambda> at 0x0000023A1B6051F0>
6
6
g = [lambda x:x*2, lambda y:y*3, lambda z:z+1]

print(g[0](1), g[1](1), g[2](1))

运行结果

2 3 2

eval()函数

功能:
  将字符串 str 当成有效的表达式来求值并返回计算结果。
语法:
  eval(source[, globals[, locals]]) -> value。
参数:
  source:一个Python 表达式或函数compile()返回的代码对象 。
  globals:可选。必须是 dictionary 。
  locals:可选。任意映射对象。

s = "print('abcde')"
eval(s)

x = 2
y = 3
z = eval("x+y")
print(z)

dict1 = {
    
    "a":1, "b":2}

d = eval("a+b", dict1)
print(d)
abcde
5
3

递归函数

  递归函数指的是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己。递归类似于大家中学数学学习过的“数学归纳法”。 每个递归函数必须包含两个部分:

  1. 终止条件
    表示递归什么时候结束。一般用于返回值,不再调用自己。
  2. 递归步骤
    把第 n 步的值和第 n-1 步相关联。

  递归函数由于会创建大量的函数对象、过量的消耗内存和运算能力。在处理大量数据时,谨慎使用。

代码示例:使用递归函数计算阶乘(factorial)

def factorial(n):
    if n == 1:
        return n
    else:
        return n * factorial(n-1)
    
if __name__ == "__main__":
    print(factorial(5))

在这里插入图片描述

代码示例:实现汉诺塔

游戏规则:从左到右 A B C 柱 大盘子在下, 小盘子在上, 借助B柱将所有盘子从A柱移动到C柱, 期间只有一个原则: 大盘子只能在小盘子的下面。
案例1
  只有一个盘子时,则直接有A,移动到C 完成。
案例2
  如果有两个盘子时,移动方案如下:
  A—>B #借助B,帮助C拿到最后一个盘子
  A—>C #最后一个盘子移动完成后,剩余的盘子已经全部到B上了
  B—>C #将剩余的盘子移动到C上,完成
案例3
  如果有三个盘子,盘子数量N = 3,移动方案如下:
在这里插入图片描述
  如果有四个盘子,盘子数量N = 4,移动方案如下:
在这里插入图片描述
规律分析:

  1. 当盘子只有一个是,即N=1,只有一个动作,从A移动到C即结束。
  2. 当有N个盘子时:
    1. 上半部分: 移动一定和n-1盘子移动时的动作相同。出发地都是A,只不过,n-1个盘子移动的目的是B,而不是C。这样方便取出最后一个盘子
    2. 中间部分: 一定是由A移动到C
    3. 下半部分: 此时等待移动的盘子已经都在B上,而不是A上,移动步骤类似于n-1个盘子的移动。出发地是B,目的地是C

递归分析:

  1. 经过上面例子可以得到。如果想要移动n个盘子到指定目的,那么一定要先将n-1个盘子移动到备用柱上。
  2. 当n-1个盘子移动后,必定要将最后一个盘子移动到C上。
  3. 经过上面的调换后,剩下待处理的盘子还有n-1个,此时盘子已经在B上而不是在A上。此时需要从新判断剩余的盘子个数。如果依然大于1个那么还是需要按照1的步骤移动第n-1个盘子之上的所有盘子共n-2到A上。从而好让第n-1个盘子从B移动到C。

总结:到第3步时,发现和有和第1步第2步类似地方。只需要改变盘子的目的点和出发点,就能刚好递归。

def move(n,a,b,c):
    if n == 1: 
        print(a,"--->",c)
    else:
        move(n-1,a,c,b)
        print(a,"--->",c)
        move(n-1,b,a,c)
        
if __name__ == "__main__":
    move(3,"A","B","C")

运行结果

A ---> C
A ---> B
C ---> B
A ---> C
B ---> A
B ---> C
A ---> C

嵌套函数(内部函数)

 &emsp嵌套函数: 在函数内部定义的函数!

代码示例:嵌套函数定义

def f1():
    print("f1 is running")
    def f2():
        print("f2 is running")

    f2()

f1()
f1 is running
f2 is running

  上面程序中,f2()就是定义在 f1 函数内部的函数。f2()的定义和调用都在 f1()函数内部。

一般在什么情况下使用嵌套函数?

  1. 封装 - 数据隐藏
    外部无法访问“嵌套函数”。
  2. 贯彻 DRY(Don’t Repeat Yourself) 原则
    嵌套函数,可以让我们在函数内部避免重复代码。
  3. 闭包。

使用嵌套函数避免重复代码:

def printChineseName(name,familyName):
    print("{0} {1}".format(familyName,name))

def printEnglishName(name,familyName):
    print("{0} {1}".format(name, familyName))
#使用 1 个函数代替上面的两个函数
def printName(isChinese, familyname, name):
    def inner_print(a, b):
        print("{0}, {1}".format(a, b))
    
    if isChinese:
        inner_print(familyname, name)
    else:
        inner_print(name, familyname)
    
if __name__ == '__main__':
    printName(True, "Feng", "San")
    printName(False, "Feng", "Russell")
Feng, San
Russell, Feng

nonlocal 关键字

nonlocal 用来声明外层的局部变量。
global 用来声明全局变量。

使用 nonlocal 声明外层局部变量

#测试 nonlocal、global 关键字的用法
a = 100

def outer():
    b = 10
    def inner():
        nonlocal b
        print(b)
        b = 20
    inner()
    print(b)
    global a
    print(a)
    a = 200

outer()
print(a)

LEGB 规则

  Python 在查找“名称”时,是按照 LEGB 规则查找的:

Local-->Enclosed-->Global-->Built in
  • Local 指的就是函数或者类的方法内部。
  • Enclosed 指的是嵌套函数(一个函数包裹另一个函数,闭包)。
  • Global 指的是模块中的全局变量。
  • Built in 指的是 Python 为自己保留的特殊名称。

  如果某个 name 映射在局部(local)命名空间中没有找到,接下来就会在闭包作用域(enclosed)进行搜索,如果闭包作用域也没有找到,Python 就会到全局(global)命名空间中进行查找,最后会在内建(built-in)命名空间搜索 (如果一个名称在所有命名空间中都没有找到,就会产生一个 NameError)。

#测试LEGB 
# str = "global"
def outer():
    # str = "outer"
    def inner():
        # str = "inner"
        print(str)

    inner()

outer()

  依次修改注释后,可以观察控制台打印的内容,体会 LEBG 的搜索顺序。

猜你喜欢

转载自blog.csdn.net/weixin_45031468/article/details/112548337
今日推荐