Python 中定义和调用一个函数之间的区别

290 阅读6分钟

Python中的函数是适合初学者话题之一!大多数人在基本水平上了解什么是函数。然而,在Python中定义和调用函数有更多的细节和细微差别。

与编码和 Python 中的大多数事情一样,没有什么比一个好的比喻更能描绘出幕后发生的事情。

在这篇文章中,你将读到Python中的函数如何像咖啡机。你将读到以下内容

  • 参数和论据
  • 定义和调用函数
  • 使用return 语句将数据从一个函数中移出

是时候给自己泡杯咖啡了,坐下来(或者站着,如果像我一样,你使用站立式办公桌),享受咖啡和文章。

一台咖啡机需要什么?

当然,有许多不同类型的咖啡机。我就用我厨房长椅上的那台作为例子。这就是它。

但是,这个比喻也适用于其他类型的咖啡机!

咖啡机的使用说明书会告诉你在制作咖啡之前需要的东西。

  • 磨碎的咖啡或咖啡豆

让我们来看看一个伪函数签名--你在定义 "咖啡机 "函数时要写的一行。

def make_coffee(water, electricity, coffee):

该函数定义有三个参数。这意味着为了使这个函数工作,它需要一些东西来填补这三个占位符。

定义函数是不够的。访问一个函数定义,无论你是自己写还是从模块中导入,都相当于买了咖啡机,拆了包装,然后在厨房里找地方放。

你需要把它打开...

打开咖啡机 - 在 Python 中调用一个函数

在你打开咖啡机之前,你必须把原料放进去。机器有一个地方为这些东西准备好了。这些占位符是。

  • 放水的水箱
  • 供电的插头
  • 咖啡豆的支架

这些是参数。它们是在你购买机器时就存在的占位符--或定义了功能。

现在你需要把需要的东西放在机器里。

你可以在水箱中使用自来水,或过滤水,或瓶装水(真的吗!)。而如果你使用咖啡豆,你可能有选择的余地。

无论你选择什么,都将是你调用函数时的参数

下面是一个函数调用可能是这样的。

make_coffee(
    tap_water,
    electricity_from_wall_socket,
    blue_espresso_pod,
)

调用函数相当于打开机器并按下按钮来制作咖啡。

当你调用一个函数时使用的括号就是 Python 中函数的 "开 "按钮。事实上,大多数设备上典型的 "on "按钮与大括号或小括号之间有相似之处( )

你知道咖啡机如何工作吗?

如果你只是想用咖啡机来煮咖啡,你不需要知道咖啡机内部是如何工作的。它有马达吗?电子设备如何?你并不关心,只要你能把水放进水箱,把咖啡豆放进支架,插上机器,然后打开它。

当你使用一个函数时,无论它是你写的还是别人写的,你都不需要知道函数定义里面有什么。

只要你知道如何使用这个函数,你就不需要知道里面写的是什么代码。你需要知道需要哪些参数,函数返回什么,但不需要知道函数如何执行它的动作。

在咖啡机的比喻中,说明书并没有告诉你机器内部是如何工作的。它只是告诉你如何使用它。

然而,如果你是一个制造咖啡机的工程师,或者你想打开你的咖啡机来修理它或(也许)改进它,那么你需要知道它是如何工作的。你需要知道函数定义中的代码--特别是如果你是编写它的人的话

煮咖啡并确保不浪费咖啡

所以,你已经把水和咖啡豆放进去,并把机器插入墙上的插座。

你把它打开。

你听到呼呼的声音,短短的一秒钟后,咖啡开始从机器顶部的喷嘴中倾泻而出......

咖啡直接倒入底部的排水盘,最终溢出,在你的厨房长椅上弄得一团糟。

哎呀!

我们很快就会回到这个问题上。

机器会返回什么?

函数会返回数据。即使是 Python 中那些 "不返回任何东西 "的函数也会返回对象None 。一个 Python 函数不可能什么都不返回。相反,当没有其他东西可以返回时,它会返回None

然而,许多函数确实会返回一些数据。让我们看一下这个例子。

import random

def do_something(first, second):
    result = first + second + random.randint(-5, 5)
    return result

敏锐的读者可能会注意到,在这个函数中不需要变量result ,但是为了接下来的讨论,我已经把它包括进去了。

这个函数的返回值是什么?这是一个迂腐的答案,但在这种情况下,迂腐是重要的。

该函数返回result 。它没有返回一个名为result 的变量。它返回的是本地变量result 的内容

如果一个变量是一个包含数据的盒子,而变量名是盒子外面的标签,那么函数并不返回盒子,而是把它翻过来,返回它的内容。

这就是为什么下面的代码返回一个NameError

import random

def do_something(first, second):
    result = first + second + random.randint(-5, 5)
    return result

do_something(3, 5)
print(result)

错误说:name 'result' is not defined 。在这个程序的主范围内,result 这个名字从未被创建过。它只作为一个局部变量存在于函数do_something() 的范围内。

那么,咖啡怎么了?你用一个调用打开了咖啡机,这个调用可能看起来像这样。

make_coffee(
    tap_water,
    electricity_from_wall_socket,
    blue_espresso_pod,
)

该函数返回咖啡液,咖啡液从咖啡机的喷嘴中涌出。但是你并没有创建一个变量来收集函数返回的咖啡。你没有存储返回的数据。就像咖啡一样,如果你不马上使用它或把它储存在某个地方,函数返回的数据就会丢失。

你可以试试下面的方法。

coffee_cup = make_coffee(
      tap_water,
      electricity_from_wall_socket,
      blue_espresso_pod,
)

现在,你将返回的咖啡收集在一个名为coffee_cup 的变量中。

是时候再做一杯咖啡了吗?

最后的话

咖啡机的比喻是我在编程中最喜欢的一个。像所有的类比一样,它并不完美,而且你能走多远是有限制的。当你转到默认参数或*args**kwargs ,你可能需要 "放弃咖啡"。

然而,它很好地描述了在 Python 中定义和调用一个函数之间的区别,以及参数和参数之间的区别。它还提供了一个很好的视觉效果,说明当一个函数返回数据时,会发生什么,以及当你调用函数时,你需要如何在一个变量中收集这些数据。