python——函数(三)

目录

lambda表达式和匿名函数

目录

lambda表达式和匿名函数

eval()函数的用法和注入安全隐患问题

递归函数_函数调用内存分析_栈帧的创建

嵌套函数_内部函数_数据隐藏

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

使用1个函数代替上面的两个函数

nonlocal和global关键字

LEGB规则



lambda表达式和匿名函数

lambda表达式可以用来声明匿名函数。lambda函数是一种简单的、在同一行中定义函数的方法。lambda函数实际生成了一个函数对象。

lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。

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

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

lambda表达式使用:

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

g = [lambda a:a*2,lambda b:b*3,lambda c:c*4]
print(g[0](6),g[1](7),g[2](8))
执行结果:

<function <lambda> at 0x0000000002BB8620>
9
12 21 32
 

eval()函数的用法和注入安全隐患问题

功能:将字符串str当成有效的表达式来求值并返回计算结果。

语法: eval(source[, globals[, locals]]) -> value

参数:

  1. source:一个Python表达式或函数compile()返回的代码对象
  2. globals:可选。必须是dictionary
  3. locals:可选。任意映射对象

#测试eval()函数
s = "print('abcde')"
eval(s)
a = 10
b = 20
c = eval("a+b")
print(c)
dict1 = dict(a=100,b=200)
d = eval("a+b",dict1)
print(d)
{⚠️⚠️⚠️eval函数会将字符串当做语句来执行,因此会被注入安全隐患。比如:字符串中含有删除文件的语句。那就麻烦大了。因此,使用时候,要慎重!!!}

递归函数_函数调用内存分析_栈帧的创建

  1. 递归(recursion)是一种常见的算法思路,在很多算法中都会用到。比如:深度优先搜索(DFS:Depth First Search)等。

  2. 递归的基本思想就是“自己调用自己”

递归函数指的是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己。每个递归函数必须包含两个部分:

  1. 终止条件

    表示递归什么时候结束。一般用于返回值,不再调用自己。

  2. 递归步骤

    把第n步的值和第n-1步相关联。

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

如下是一个简单的递归程序:

def my_recursion(n):
  print("start:" + str(n))
  if n == 1:
    print("recursion over!")
  else:
    my_recursion(n - 1)

  print("end:" + str(n))

my_recursion(3)

运算结果:

start:3 start:2 start:1 recursion over! end:1 end:2 end:3

使用递归函数计算阶乘(factorial)

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

print(factorial(5))

嵌套函数_内部函数_数据隐藏

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

def outer():
  print('outer running...')
  def inner():
    print('inner running...')​
  inner()
outer()
执行结果:

outer running...
inner running...
 

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

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

  1. 封装 - 数据隐藏

    外部无法访问“嵌套函数”。

  2. 贯彻 DRY(Don’t Repeat Yourself) 原则

  3. 嵌套函数,可以让我们在函数内部避免重复代码。

  4. 闭包

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

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

使用1个函数代替上面的两个函数

def printName(isChinese,name,familyName):
  def inner_print(a,b):
    print("{0} {1}".format(a,b))
  if isChinese:
    inner_print(familyName,name)
  else:
    inner_print(name,familyName)
printName(True,"小七","温")
printName(False,"George","Bush")

nonlocal和global关键字

nonlocal 用来在内部函数中,声明外层的局部变量。

global 函数内声明全局变量,然后才使用全局变量

使用nonlocal声明外层局部变量

#测试nonlocal、global关键字的用法
a = 100
def outer():
  b = 10
  def inner():
    nonlocal b     #声明外部函数的局部变量
    print("inner b:",b)
    b = 20
    global a      #声明全局变量
    a = 1000
  inner()
  print("outer b:",b)
outer()
print("a:",a)

LEGB规则
 

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

image-20211116111854538

Local 指的就是函数或者类的方法内部

Enclosed 指的是嵌套函数(一个函数包裹另一个函数,闭包)

Global 指的是模块中的全局变量

Built in 指的是Python为自己保留的特殊名称

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

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

我们依次将几个s注释掉,观察控制台打印的内容,体会LEBG的搜索顺序。

基于Python的计算思维训练主要涉及到函数的概念。函数Python中的基本编程结构,通过函数可以将一系列操作封装起来,提高代码的复用性和可维护性。 首先,函数的定义和调用是计算思维中重要的一部分。学习者需要理解如何使用def关键字定义函数,并且学会传入参数和返回数值。这能够帮助他们将复杂的问题拆分成更小的部分,然后再分别解决。 其次,函数的参数和返回值的运用是培养计算思维的有效途径。学习者需要理解函数的参数可以是任意类型的数据,也可以是默认值,还可以是可变数量的参数。同时,他们需要掌握函数可以返回单个数值、多个数值或者其他函数的能力。 此外,函数的嵌套和递归是培养计算思维的重要方法。学习者需要了解函数可以在其内部调用其他函数,从而实现更复杂的功能。而递归则可以帮助他们理解问题的分治和循环求解策略。 最后,函数的高阶用法和闭包也是培养计算思维的关键。学习者需要明白函数可以作为参数传递给其他函数,也可以作为返回值被另一个函数使用。此外,他们还需要掌握闭包的概念和运用,以便更好地理解函数的作用域和生命周期。 通过学习和实践以上内容,学习者不仅可以掌握Python函数的用法,还可以培养出较强的计算思维能力,从而更好地应对复杂的问题和挑战。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值