第10章-功能

函数是您定义的结构。你得决定他们是否有参数。您也可以添加关键字参数和默认参数。函数是以 def 关键字、函数名和冒号。下面是一个简单的例子:

>>> def a_function():
        print("You just created a function!")

这个函数除了打印一些文本外什么都不做。要调用函数,需要键入函数名,然后键入左括号和右括号:

>>> a_function()
You just created a function!

简单,嗯?

空函数(存根)

有时,当您编写一些代码时,您只想编写函数定义而不在其中放入任何代码。我这样做是为了勾勒出一个轮廓。它可以帮助您了解应用程序的布局。下面是一个例子:

>>> def empty_function():
        pass

这里有一些新的东西: pass 声明。它基本上是一个空操作,这意味着当 pass 被执行,什么都没有发生。

向函数传递参数

现在我们准备学习如何创建一个可以接受参数的函数,以及如何将所说参数传递给函数。让我们创建一个简单的函数,可以将两个数字相加:

>>> def add(a, b):
        return a + b

>>> add(1, 2)
3

所有函数都返回一些内容。如果你不告诉它归还什么,它就不会归还任何东西。在这种情况下,我们让它返回 A+B .如您所见,我们可以通过传递两个值来调用函数。如果传递的参数不够或太多,则会出现错误:

>>> add(1)
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
TypeError: add() takes exactly 2 arguments (1 given)

还可以通过传递参数的名称来调用函数:

>>> add(a=2, b=3)
5
>>> total = add(b=4, a=5)
>>> print(total)
9

您会注意到,只要它们的名称正确,将它们传递给函数的顺序是什么并不重要。在第二个示例中,您可以看到我们将函数的结果赋给一个名为 全部的 .这是调用函数的常用方法,因为您需要对结果做一些事情。您可能想知道如果我们传入带有错误名称的参数会发生什么。它能工作吗?让我们看看:

>>> add(c=5, d=2)
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
TypeError: add() got an unexpected keyword argument 'c'

哎呀!我们收到一个错误。这意味着我们传递了一个函数无法识别的关键字参数。巧合的是,关键字参数是我们的下一个主题!

关键字参数

函数还可以接受关键字参数!它们实际上可以接受常规参数和关键字参数。这意味着您可以指定哪些关键字是哪个关键字,然后将它们传入。您在前面的示例中看到了这种行为。

>>> def keyword_function(a=1, b=2):
        return a+b

>>> keyword_function(b=4, a=5)
9

您也可以在不指定关键字的情况下调用此函数。此函数还演示了默认参数的概念。怎样?好吧,尝试在完全没有参数的情况下调用函数!

>>> keyword_function()
3

函数返回数字3!为什么?原因是 ab 默认值分别为1和2。现在,让我们创建一个同时具有常规参数和几个关键字参数的函数:

>>> def mixed_function(a, b=2, c=3):
        return a+b+c

>>> mixed_function(b=4, c=5)
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
TypeError: mixed_function() takes at least 1 argument (2 given)
>>> mixed_function(1, b=4, c=5)
10
>>> mixed_function(1)
6

上面的代码中有3个例子。让我们逐一检查一下。在第一个示例中,我们尝试只使用关键字参数调用函数。这将给我们带来一个令人困惑的错误。回溯说明我们的函数至少接受一个参数,但给出了两个参数。这是怎么回事?事实上,第一个参数是必需的,因为它没有设置为任何值,所以如果只使用关键字参数调用函数,则会导致错误。

对于第二个示例,我们调用具有3个值的混合函数,命名其中两个值。这是可行的,并给出了预期的结果,即1+4+5=10。第三个例子展示了如果我们只通过传递一个值来调用函数会发生什么……一个没有默认值的值。这也可以通过取“1”并将其添加到“2”和“3”的两个默认值中,得到“6”的结果!那不酷吗?

* ARGS和 * *克沃斯

还可以通过使用特殊语法设置函数以接受任意数量的参数或关键字参数。要获取无限参数,请使用 * 参数和对于无限关键字参数,请使用 * *kwargs. The "args" and "kwargs" words are not important. That's just convention. You could have called them * 比尔和 * *泰德和它的工作原理是一样的。这里的键是星号的数目。

Note: in addition to the convention of * ARGS和 * *夸格斯,你也会看到 A和 **kw from time to time.*

让我们来看一个简单的例子:

>>> def many(*args, **kwargs):
        print(args)
        print(kwargs)

>>> many(1, 2, 3, name="Mike", job="programmer")
(1, 2, 3)
{'job': 'programmer', 'name': 'Mike'}

首先,我们使用新语法创建函数,然后用三个正则参数和两个关键字参数调用它。函数本身将打印出两种类型的参数。如你所见, args 参数变为元组并 关键字参数 变成字典。您将在python源代码和许多第三方python包中看到这种类型的代码。

关于范围和全局的注释

python的概念是 范围 就像大多数编程语言一样。作用域将告诉我们何时变量可用以及在何处可用。如果我们在函数内部定义变量,那么这些变量只能在函数内部使用。一旦函数结束,就不能再使用它们,因为它们 超出范围 .让我们来看一个例子:

def function_a():
    a = 1
    b = 2
    return a+b

def function_b():
    c = 3
    return a+c

print( function_a() )
print( function_b() )

如果运行此代码,将收到以下错误:

NameError: global name 'a' is not defined

这是因为变量 a 仅在第一个函数中定义,在第二个函数中不可用。你可以通过告诉 Python a 是一个 全球的 变量。让我们看看是怎么做到的:

def function_a():
    global a
    a = 1
    b = 2
    return a+b

def function_b():
    c = 3
    return a+c

print(function_a())
print(function_b())

因为我们告诉python a 全局,这意味着该变量在我们的程序中无处不在。这通常是个坏主意,不推荐。不建议这样做的原因是,这使得很难判断何时定义了变量。另一个问题是,当我们在一个地方定义一个全局时,我们可能会意外地在另一个地方重新定义它的值,这可能会导致以后难以调试的逻辑错误。

编码提示

新程序员需要学习的最大问题之一是“不要重复自己(dry)”。这个概念是您应该避免多次编写相同的代码。当您发现自己这样做时,您就知道代码块应该进入一个函数。这样做的一个重要原因是,您几乎肯定将来需要再次更改这段代码,如果它在多个位置,那么您需要记住所有这些位置的位置并更改它们。

复制和粘贴整个代码块就是 意大利面代码 .尽量避免这种情况。在某种程度上,你会后悔的,要么是因为你必须修复它,要么是因为你会找到其他人的代码,你必须在这些问题上维护它们。

总结

现在,您已经掌握了有效使用函数所必需的基础知识。您应该练习创建一些简单的函数,并尝试以不同的方式调用它们。一旦你对函数进行了一些尝试,或者你认为你已经完全理解了其中的概念,你就可以开始下一章的课程了。