一文掌握Python内部函数:函数作为返回和闭包

2025年03月17日02:33:07 科技 1510

一文掌握Python内部函数:函数作为返回和闭包 - 天天要闻

Python 中,函数被认为是一等公民,这意味着它们可以像对待任何其他对象一样对待。这种对一类函数的支持允许使用高阶函数,这些函数可以接受其他函数作为参数或返回函数作为结果。这个强大的功能增强了 Python 编程的灵活性和表现力,允许更动态和功能化的编程模式。

为了理解为什么这些能力是有用的,编写一个返回其参数的恒等式函数。

def identity(number): 
  return number

identity(10)

#10

现在编写另一个函数来求平方。

def square(number):
  return number**2

square(6)

#36

现在,将这两种功能组合到一个函数中。为此,可以将这两个函数编写为另一个函数的内部函数。

Python 内部函数:

在 Python 中,内部函数是在另一个函数的主体中定义的函数。它也称为嵌套函数。们的例子中:

def doWithNumber(number, squareIt = False):

  # identity function as inner function of doWithTheNumber
  def identity(): 
    return number

  # square function as inner function of doWithTheNumber
  def square():
    sq = number**2
    return sq

  # if else block to execute one of the function
  if squareIt == True:
    return square()
  else:
    return identity()

内部函数的作用域在外部函数内,这意味着它可以访问外部函数的变量和参数。

在上面的例子中, identity()square() 被定义在 doWithNumber(number, squareIt= False) .内部函数可以访问外部函数的变量和参数,例如,两者都 i可以访问 number ,但反之则不然, doWithNumber(number, squareIt= False) 无权访问 哪个是 的内部变量 square() 。这称为词法范围或闭包。

内部函数在各种场景中都很有用,例如:

  1. 封装:内部函数允许我们将一个功能封装在另一个函数的范围内,将相关代码保持在一起并与程序的其余部分分开。上面的函数 doWithNumber(number, squareIt= False) 是封装的一个很好的例子。
  2. 闭包:内部函数可以创建闭包,这些函数可以记住封闭范围内的值,即使它们不再存在。这允许在函数调用之间保留状态。
  3. 装饰器:内部函数通常用于装饰器中,这是一种通过用附加功能包装函数或类来修改它们的行为的方法。内部函数用作包装器,将所需的功能添加到原始函数中。

返回函数和闭包:

一个函数可以返回另一个函数。例如,可以稍微修改我们的 modifyNumber 数字函数以返回内部函数而不是执行它们。

def modifyNumber(squareIt = False):

  # identity function as inner function of doWithTheNumber
  def identity(number): 
    return number

  # square function as inner function of doWithTheNumber
  def square(number):
    sq = number**2
    return sq

  # if else block to execute one of the function
  if squareIt == True:
    return square
  else:
    return identity

现在,如果执行外部函数,这将为提供另一个函数。请记住,它不会执行任何函数,而是会提供另一个可执行函数。

justPrint = modifyNumber()

上面的代码将返回我们内部函数 identity(number) 。现在我以用参数调用 justPrint 了。

justPrint(15)

#15

Or

squareNumber= modifyNumber(True)

squareNumber(25)

#625

这里发生了什么?

首先,当调用 squareNumber = modifyNumber(True) 它时,它会设置 squareIt = True .

然后它定义了我们的两个函数 identity()square() .

然后它运行 if-else 块,因为 squareIt = True ,该块返回 square ;这是一个函数。

现在 squareNumber = square 相当于。

def squareNumber(number)
  sq = number**2
    return sq

因此,当调用 squareNumber(25) 它时,它返回了 625。

闭包是与内部函数和返回函数相关的重要概念。当嵌套/内部函数从其包含(封闭)函数的作用域引用变量时,即使封闭函数已完成执行,也会发生闭包。

比如之前的函数只能返回 identity 和 square,如果想添加额外的功能怎么办?修改一下函数。

def modifyNumber(power):
 def raisePower(number):
  return number ** power

 return raisePower

如果我们调用外部函数

identity = modifyNumber(1)

该函数将返回到另一个函数,即 raisePower .请记住,返回的是尚未执行的函数。为了执行它,必须调用它。

identity(10)
#10
identity(25)
#25

为什么当调用 identity(10) 时返回 10。因已经看到设置 identity = modifyNumebr(1)power = 1 and 它的集合 identity = raisePower ,它等价于

def identity(number):
  return number ** power

但是raisePowe函数没有名为 power 的变量。该变量 power 位于函数的作用域 modifyNumebr 内,该函数已完成执行。

现在调用 identity(10) 的时候,它将如何执行这一行代码 return number ** power ,它如何获取它的值 power = 1

在 Python 中,当外部函数完成执行并返回内部函数时,它会将内部函数与其封闭环境或闭包一起打包。这意味着函数对象保留其包含作用域中定义的所有变量和名称的引用。这允许内部函数稍后访问和使用这些变量,即使外部函数已完成其执行并且这些变量通常超出范围。

这有点像父母给孩子留下遗产。即使父母可能已不复存在,孩子仍然可以访问所有继承的资产。

可以根据需要多次调用我们的外部函数。

squareNumber = modifyNumber(2)
cubeNumber =  modifyNumber(3)
rootNumber = modifyNumber(0.5)

可以随心所欲地调用我们的内在功能。

squareNumber(10)
#100
squareNumber(5)
#25
cubeNumber(3)
#27
rootNumber(25)
#5.0
rootNumber(16)
#4.0

或者我们可以将这种内部功能与嵌套的俄罗斯娃娃进行比较。可以嵌套尽可能多的函数。

def eventPlanner(evenName):
  print(f'Welcome to {evenName}')
  listOfParticipant = []
 
  def register(name):
    listOfParticipant.append(name)
    print(listOfParticipant)
    
    listOfTask = []
    def addTask(task):
      listOfTask.append(task)
      print(listOfTask)
    
    return addTask
  return register

添加了三层功能,一个在另一个内部。这就像一个洋葱,调用一个层会让我们返回到另一个具有层的函数。

如果调用第一层,它将返回一个注册函数。

fareRegistration = eventPlanner("1st School Fair")

#Welcome to 1st School Fair

现在可以调用第二层。它将打印已注册人员的列表,并返回给我们一个任务功能。

enamTasks = fareRegistration("Enam")

# ['Enam']

似乎只有一名会员注册了票价。让再注册一个。

kalamTasks = fareRegistration("Kalam")

#['Enam', 'Kalam']

这里需要注意的一件事是,由于闭包,它为我们打印了两个名称,尽管外部函数完成了它的执行,但它提供了直接的内部函数,直到变量的最新状态。

enamTasks("visit tea stall")
#['visit tea stall']

enamTasks("visit book stall")
#['visit tea stall', 'visit book stall']

enamTasks("attend Magic Show")
#['visit tea stall', 'visit book stall', 'attend Magic Show']

同样,可以为同样注册了票价的 Kalam 先生添加任务。

kalamTasks("Perform Magic")
#['Perform Magic']

总之,这些是 Python 中强大的概念。例如,内部函数允许我们在另一个函数的主体中定义函数,从而提供了一种封装相关功能并保持代码模块化和组织化的方法。内部函数可以访问封闭函数的变量和参数,使它们能够利用和操作其包含范围内的数据。

从其他函数返回函数为我们的代码增加了另一层灵活性。它允许我们创建高阶函数,根据特定要求生成和自定义函数。这种能力使我们能够编写更通用和可重用的代码,并促进函数式编程模式。

当内部函数保留对其封闭作用域的引用,捕获必要的变量和名称时,就会形成与返回函数密切相关的闭包。这种机制使内部函数能够访问和利用其包含环境的状态,即使在封闭函数完成执行之后也是如此。闭包为函数提供持久性和上下文,允许它们保留特定于其创建点的数据和行为。

这些概念使我们能够编写模块化、可重用和可定制的功能,从而增强代码的可读性、可维护性和效率。无论我们是将它们用于数据封装、函数工厂、回调还是其他目的,理解和利用内部函数、返回函数和闭包都可以扩展我们的编程工具包,并使我们能够为各种问题编写优雅而有效的解决方案。

科技分类资讯推荐

联想憋了40年的大招:自研5nm芯片上市,这次真没放鸽子 - 天天要闻

联想憋了40年的大招:自研5nm芯片上市,这次真没放鸽子

最近科技圈最热闹的事,莫过于联想在自家新平板上塞了颗"中国芯"。这事要搁五年前,网友能把键盘敲出火星子——毕竟在很多人印象里,联想除了组装电脑就是卖手机,突然掏出颗5纳米芯片,比四川变脸还让人意外。说起联想和芯片的恩怨情仇,那真是三天三夜唠
国产手机冲高端:别光顾着堆料,先学会把价格打上去 - 天天要闻

国产手机冲高端:别光顾着堆料,先学会把价格打上去

最近翻看Counterpoint的2025年一季度手机市场报告,有个数据看得人直嘬牙花子:苹果手机的平均售价还是816美元,相当于5800多块人民币,而小米的均价才155美元,折合人民币1100出头。这价格差得,都能买五台小米凑个"五福临门
moto razr 60系列三款新机发布,3499元起售 - 天天要闻

moto razr 60系列三款新机发布,3499元起售

继此前moto方面确认,新款小折叠razr 60系列即将5月8日在国内市场正式发布后,陆续在预热活动中公布的产品端相关信息也吸引了众多消费者的关注。昨日官方正式发布了razr 60系列三款机型,其中包含一款被命名为razr 60 Pro的新机,该系列机型的售价则从3499元起跳,参与国补后最低仅需2999元。外观方面,razr 60系列三款机型...
微软工程师揭秘 Windows 剪贴板优化方式:是如何获得最佳性能的 - 天天要闻

微软工程师揭秘 Windows 剪贴板优化方式:是如何获得最佳性能的

IT之家 5 月 9 日消息,据外媒 Neowin 今日报道,微软高级工程师雷蒙德・陈在微软网站的专栏《The Old New Thing》更新博文,他详细说明了 Windows 本地剪贴板与其他剪贴板管理器的不同之处,并解释了这种设计为何有益。IT之家注:Windows 提供了默认的剪贴板,可以通过“设置”开启,也可以通过 Win + V 快捷键直接打开。
上线“随申兑”、扩大“免申即享”范围……上海无感化服务让企业轻装上阵 - 天天要闻

上线“随申兑”、扩大“免申即享”范围……上海无感化服务让企业轻装上阵

不用自己申请,补贴、奖励等“丝滑”入账……上海大力推进的“免审即享”,通过大数据分析、人工智能辅助等工具,将政策精准送到企业身边。上海正加力提速推进2025年优化营商环境“十大攻坚突破任务”,聚焦企业需求最迫切、协同推进要求高的十个事项,加力推出新一批增量举措,合力解决营商环境建设中的“老大难”问题。上...
二十年前的586电脑,奔III处理器+Win98系统,闲鱼卖2680元 - 天天要闻

二十年前的586电脑,奔III处理器+Win98系统,闲鱼卖2680元

之前我写了个九十年代的海尔电脑机箱,阅读量挺高的,你们爱看这玩意?那就继续回忆杀,再写另一个“收藏级”的586老电脑,自带纯平显示器。它就是二十五年前的联想天禧6622电脑,居然是大全套收藏级成色,主机箱、显示器、键盘、光驱、软驱一应俱全,
消息称三星显示最早下月启动三星电子首款三折叠手机显示面板量产 - 天天要闻

消息称三星显示最早下月启动三星电子首款三折叠手机显示面板量产

IT之家 5 月 9 日消息,韩媒 daily.hankooki 当地时间今日报道称,三星显示预计最早 6 月、最晚 7 月开始量产三星电子首款三折叠手机(IT之家注:即所谓的 Galaxy G Fold)的显示面板。▲ 三星显示 Flex G 三折叠概念设备报道指出,由于三折叠手机在整体智能手机市场尚属新形态,因此三星显示的面板产量初期预计落在 20~30
Retroid Pocket Mini V2 安卓游戏掌机发布,1399 元 - 天天要闻

Retroid Pocket Mini V2 安卓游戏掌机发布,1399 元

IT之家 5 月 9 日消息,Retroid 今日推出安卓游戏掌机 Pocket Mini V2,迭代机型主要解决初代的显示问题,更换到该公司 Pocket Classic 掌机的同款 3.92 英寸 AMOLED 屏幕,其余配置参数一致,目前仅提供黑色,官网首发售价 1399 元。Retroid Pocket Mini V2 搭载高通骁龙 865 处理器,