从python函数的调用与引用(函数名后面到底加不加括号),聊聊函数的基本原理

📁 365足球体育亚洲版 📅 2025-10-13 17:19:53 👤 admin 👁️ 3037 ❤️ 74
从python函数的调用与引用(函数名后面到底加不加括号),聊聊函数的基本原理

本篇文章适合python初级开发者阅读。

在我们使用python的过程中会发现:对于一个函数,有时候使用的是函数名加括号,例如func_name(),有时候直接使用函数名本身func_name。这两者有什么不同呢?各自应用于什么样的场景呢?

简单来说,func_name()代表调用函数,func_name代表引用函数。

调用函数:就是让函数执行其中的代码。

引用函数:当需要将函数作为对象传递或赋值时使用。

但要深入理解 python 中函数的调用和引用,我们可以从以下几个方面展开讨论:函数对象的本质、内存管理、以及调用和引用的具体区别。

1. 函数的本质——对象

在python中,函数是一等对象(first-class object),这就意味着函数和其他对象(比如数字、字符串、列表等)一样,可以被赋值给变量、作为参数传递给其他函数,甚至存储在数据结构中(如列表或字典中)。

例如:

def my_func():

print("Hello")

# 函数对象被赋值给变量

func_ref = my_func

# func_ref 和 my_func 引用的是同一个函数对象

func_ref() # 调用的是 my_func 的逻辑,输出 "Hello"

当我们定义一个函数时,例如 def my_func(),python在内存中为该函数创建了一个函数对象,并将函数名 my_func 指向这个对象。

2. 函数调用——执行代码

当代码为 my_func() 时,括号的作用是触发函数的执行。python会跳转到该函数的代码,并执行其中的每一条指令。

在调用函数时,python会为该函数的调用分配栈帧(stack frame)。每次调用函数时,都会在内存中分配一个新的栈帧,用来存储该函数的局部变量、参数以及返回地址等信息。当函数执行完毕后,栈帧会被销毁,并释放相应的内存。

def my_func():

print("Hello")

my_func() # 立即调用,输出 "Hello"

也就是说在这个过程中,发生了以下步骤:

python 遇到 my_func(),开始调用函数。为 my_func 分配栈帧,保存执行函数的上下文(如局部变量和参数)。执行 print("Hello")。函数执行结束,释放栈帧,返回到调用者的位置。

3. 引用函数——内存中的函数对象

回到文章最前面的例子:当写出 func_ref = my_func 这种形式时,实际上并没有调用函数,而是让 func_ref 这个变量指向了 my_func 所指向的那个函数对象。也就是说,my_func 和 func_ref 现在都指向同一个内存地址中的函数对象。

此时并不会触发任何代码的执行,也不会有新的栈帧创建。引用只是创建了一个新的指针,指向现有的函数对象。内存中也不会增加新的函数代码或执行上下文。

def greet():

print("Hello, world!")

greeting_function = greet # 只是引用,不会调用函数,也不执行代码

greeting_function() # 此时才调用函数,分配栈帧并执行代码

在这个例子中:

greet 是指向函数对象的引用。

greeting_function 也是指向同一个函数对象的引用。

只有在调用 greeting_function() 时,才会执行该函数的代码,并创建栈帧。

4. 高阶函数——函数作为参数

python 函数可以作为参数传递给其他函数。这种情况下,传递的是函数的引用,而不是执行它。在这种场景下,传递的是内存中已有的函数对象的引用。

def execute_function(func):

func() # 调用传入的函数

def say_hello():

print("Hello")

execute_function(say_hello) # 传递函数引用,执行时调用 say_hello

# 输出:Hello

在 execute_function(say_hello) 中,我们将 say_hello 函数作为对象传递给 execute_function,但并没有立即执行 say_hello。只有在 func() 被调用时,say_hello 的逻辑才被执行。

5. 小结

函数引用(func_name):仅仅是在内存中指向一个函数对象,不会分配新的内存给栈帧或执行环境。引用可以赋值给变量、传递给其他函数、作为参数使用。引用并不会导致函数执行。函数调用(func_name()):触发函数执行,python 会为该调用分配新的栈帧,包括局部变量、参数、返回地址等。调用后,python 执行函数中的代码,并在完成后销毁栈帧,释放内存。两者的本质区别在于,函数引用是指向函数对象的操作,不会触发代码执行,也不会引起内存的额外分配;而函数调用则会在内存中创建新的栈帧,并执行函数的逻辑。

相关推荐