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

自由坦荡的智能 2025-03-22 01:07:19

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

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

def identity(number): return numberidentity(10)#10

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

def square(number): return number**2square(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() 。这称为词法范围或闭包。

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

一个函数可以返回另一个函数。例如,可以稍微修改我们的 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)#10identity(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)#100squareNumber(5)#25cubeNumber(3)#27rootNumber(25)#5.0rootNumber(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 中强大的概念。例如,内部函数允许我们在另一个函数的主体中定义函数,从而提供了一种封装相关功能并保持代码模块化和组织化的方法。内部函数可以访问封闭函数的变量和参数,使它们能够利用和操作其包含范围内的数据。

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

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

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

0 阅读:0

自由坦荡的智能

简介:感谢大家的关注