如何在Python 3中定义函数

介绍

A function is a block of instructions that performs an action and, once defined, can be reused. Functions make code more modular, allowing you to use the same code over and over again.

Python具有许多您可能熟悉的内置函数,包括:

  • print(),它将对象打印到终端
  • int(),它将字符串或数字数据类型转换为整数数据类型
  • len(),它返回对象的长度

函数名称包括括号,可能包括参数。

在本教程中,我们将介绍如何定义自己的函数以在编码项目中使用。

先决条件

您应该已经安装了Python 3,并在计算机或服务器上设置了编程环境。如果您还没有设置编程环境,可以参考适用于您操作系统(Ubuntu、CentOS、Debian等)的本地编程环境或者服务器上的编程环境的安装和设置指南。

定义一个函数

让我们从将经典的“Hello, World!”程序转换为函数开始。

我们将在我们选择的文本编辑器中创建一个新的文本文件,并将程序命名为hello.py。然后,我们将定义函数。

A function is defined by using the def keyword, followed by a name of your choosing, followed by a set of parentheses which hold any parameters the function will take (they can be empty), and ending with a colon.

信息:要跟随本教程中的示例代码,通过运行python3命令在本地系统上打开Python交互式shell。然后,您可以通过在>>>提示之后添加、复制或编辑示例来操作。

在这种情况下,我们将定义一个名为hello()的函数:

hello.py
def hello():

这设置了创建函数的初始语句。

从这里,我们将添加第二行,缩进4个空格,以提供函数的指令。在这种情况下,我们将打印Hello, World!到控制台:

hello.py
def hello():
    print("Hello, World!")

我们的函数现在已经完全定义,但如果此时运行程序,将不会发生任何事情,因为我们没有调用函数。

因此,在我们定义的函数块之外,让我们用hello()调用函数:

hello.py
def hello():
    print("Hello, World!")

hello()

现在,让我们运行程序:

  1. python hello.py

您应该会收到以下输出:

Output
Hello, World!

函数可能比我们上面定义的hello()函数更复杂。例如,我们可以在函数块中使用for循环条件语句等等。

例如,下面定义的函数利用条件语句检查name变量的输入是否包含元音,并使用for循环迭代name字符串中的字母。

names.py
# 定义函数 names()
def names():
    # 设置带输入的 name 变量
    name = str(input('Enter your name: '))
    # 检查 name 是否包含元音
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')

    # 遍历 name
    for letter in name:
        print(letter)

# 调用函数
names()

我们上面定义的names()函数设置了条件语句和for循环,展示了如何在函数定义中组织代码。然而,根据我们的程序意图以及我们想要设置代码的方式,我们可能想要将条件语句和for循环定义为两个单独的函数。

在程序中定义函数使我们的代码模块化和可重复使用,这样我们可以调用相同的函数而无需重写它们。

使用参数

到目前为止,我们已经看过了使用空括号的函数,这些函数不接受参数,但是我们可以在函数定义中的括号内定义参数。

A parameter is a named entity in a function definition, specifying an argument that the function can accept.

让我们创建一个小程序,该程序接受参数xyz。我们将创建一个函数,以不同的方式将参数相加。这些总和将由函数打印出来。然后我们将调用函数并将数字传递给函数。

add_numbers.py
def add_numbers(x, y, z):
    a = x + y
    b = x + z
    c = y + z
    print(a, b, c)

add_numbers(1, 2, 3)

我们为x参数传递了数字1,为y参数传递了2,为z参数传递了3。这些值与它们给出的顺序中的每个参数相对应。

该程序基本上根据我们传递给参数的值执行以下数学运算:

a = 1 + 2
b = 1 + 3
c = 2 + 3

该函数还打印abc,根据上述数学运算,我们期望a等于3b等于4c等于5。让我们运行该程序:

  1. python add_numbers.py
Output
3 4 5

当我们将123作为参数传递给add_numbers()函数时,我们得到了预期的输出。

参数通常在函数定义中被定义为变量。当你运行方法时,可以为它们赋值,将参数传递到函数中。

关键字参数

除了按顺序调用参数外,还可以在函数调用中使用关键字参数,调用者通过参数名标识参数。

使用关键字参数时,可以无序使用参数,因为Python解释器将使用提供的关键字将值与参数匹配。

让我们创建一个函数,用于显示用户的个人资料信息。我们将以username(意为字符串)和followers(意为整数)的形式传递参数给它。

profile.py
# 定义带有参数的函数
def profile_info(username, followers):
    print("Username: " + username)
    print("Followers: " + str(followers))

在函数定义语句中,usernamefollowers包含在profile_info()函数的括号中。函数的代码块以字符串形式打印有关用户的信息,利用了这两个参数。

现在,我们可以调用函数并为其分配参数:

profile.py
def profile_info(username, followers):
    print("Username: " + username)
    print("Followers: " + str(followers))

# 调用函数并分配参数
profile_info("sammyshark", 945)

# 使用关键字参数调用函数
profile_info(username="AlexAnglerfish", followers=342)

在第一个函数调用中,我们使用用户名为sammyshark,关注者数为945填入了信息,在第二个函数调用中,我们使用了关键字参数,为参数变量分配了值。

让我们运行程序:

  1. python profile.py
Output
Username: sammyshark Followers: 945 Username: AlexAnglerfish Followers: 342

输出显示了两个用户的用户名和关注者数。

这也允许我们修改参数的顺序,就像这个示例程序中的不同调用一样:

profile.py
def profile_info(username, followers):
    print("Username: " + username)
    print("Followers: " + str(followers))

# 改变参数顺序
profile_info(followers=820, username="cameron-catfish")

当我们再次使用python profile.py命令运行程序时,我们将收到以下输出:

Output
Username: cameron-catfish Followers: 820

因为函数定义保持了print()语句的相同顺序,如果我们使用关键字参数,传递给函数调用的顺序并不重要。

默认参数值

我们还可以为一个或两个参数提供默认值。让我们为followers参数创建一个默认值,值为1

profile.py
def profile_info(username, followers=1):
    print("Username: " + username)
    print("Followers: " + str(followers))

现在,我们可以只运行分配了用户名函数的函数,并且关注者数量将自动默认为1。如果需要,我们也可以仍然更改关注者数量。

profile.py
def profile_info(username, followers=1):
    print("Username: " + username)
    print("Followers: " + str(followers))

profile_info(username="JOctopus")
profile_info(username="sammyshark", followers=945)

当我们使用python profile.py命令运行程序时,我们将收到以下输出:

Output
Username: JOctopus Followers: 1 Username: sammyshark Followers: 945

使用带有值的默认参数可以让我们跳过为每个已有默认值的参数定义值。

返回一个值

您可以将参数值传递到函数中,函数也可以产生一个值。

A function can produce a value with the return statement, which will exit a function and optionally pass an expression back to the caller. If you use a return statement with no arguments, the function will return None.

到目前为止,我们已经在函数中使用了print()语句,而不是return语句。让我们创建一个程序,该程序将返回一个变量,而不是打印。

在一个名为square.py的新文本文件中,我们将创建一个程序,该程序将参数x的平方值返回给变量y。我们发出一个对square()函数的调用,并将3传递给它。

square.py
def square(x):
    y = x ** 2
    return y

result = square(3)
print(result)

我们可以运行程序并接收输出:

  1. python square.py
Output
9

整数9作为输出返回,这是我们希望Python计算出3的平方值的预期结果。

为了进一步理解return语句的工作原理,我们可以注释掉程序中的return语句:

square.py
def square(x):
    y = x ** 2
    # 返回 y

result = square(3)
print(result)

现在,让我们再次运行程序:

  1. python square.py
Output
None

在这里不使用return语句,程序无法返回一个值,因此该值默认为None

作为另一个例子,在上述的add_numbers.py程序中,我们可以将print()语句替换为return语句。

add_numbers.py
def add_numbers(x, y, z):
    a = x + y
    b = x + z
    c = y + z
    return a, b, c

sums = add_numbers(1, 2, 3)
print(sums)

在函数外部,我们将变量sums设置为以123作为参数调用函数的结果,就像我们之前所做的那样。然后我们打印sums变量。

现在让我们再次运行该程序,因为它现在有了return语句:

  1. python add_numbers.py
Output
(3, 4, 5)

我们收到了与之前使用print()语句在函数中收到的相同的数字345作为输出。这次它被作为元组输出,因为return语句的表达式列表至少有一个逗号。

函数在遇到return语句时立即退出,无论它们是否返回一个值。

return_loop.py
def loop_five():
    for x in range(0, 25):
        print(x)
        if x == 5:
            # 在 x == 5 处停止函数
            return
    print("This line will not execute.")

loop_five()

for循环中使用return语句会结束函数,因此在循环外的那一行不会运行。如果我们改用了break语句,那么在那个时候只有循环会退出,最后一个print()行会运行。

return语句退出一个函数,并在带参数的情况下返回一个值。

main()用作函数

虽然在Python中,您可以在程序底部调用函数并运行它(就像我们在上面的示例中所做的那样),但许多编程语言(如C++和Java)需要一个main函数才能执行。虽然不是必需的,但包含一个main()函数可以以逻辑方式构造我们的Python程序,将程序的最重要组件放入一个函数中。这也可以使我们的程序更易于非Python程序员阅读。

我们将首先在上面的hello.py程序中添加一个main()函数。我们将保留我们的hello()函数,然后定义一个main()函数:

hello.py
def hello():
    print("Hello, World!")

def main():

main()函数中,让我们包含一个print()语句,以便让我们知道我们在main()函数中。此外,让我们在main()函数中调用hello()函数:

hello.py
def hello():
    print("Hello, World!")


def main():
    print("This is the main function")
    hello()

最后,在程序底部我们将调用main()函数:

hello.py
def hello():
    print("Hello, World!")

def main():
    print("This is the main function.")
    hello()

main()

此时,我们可以运行我们的程序:

  1. python hello.py

我们将收到以下输出:

Output
This is the main function. Hello, World!

因为我们在main()函数内调用了hello()函数,然后只调用了main()来运行,所以Hello, World!文本只打印了一次,在告诉我们我们在主函数中的字符串之后。

接下来,我们将要使用多个函数,因此值得回顾全局和局部变量的变量作用域。如果在函数块内定义变量,您只能在该函数内使用该变量。如果想要在函数之间使用变量,最好声明全局变量。

在Python中,'__main__'是顶层代码执行的范围名称。当从标准输入、脚本或交互式提示符运行程序时,其__name__设置为'__main__'

因此,有一个约定使用以下结构:

if __name__ == '__main__':
    # 这是主程序时要运行的代码

这让程序文件可以被用作:

  • 作为主程序并运行if语句之后的内容
  • 作为模块并不运行if语句之后的内容。

不包含在此语句中的任何代码都将在运行时执行。如果将程序文件用作模块,则在运行次要文件时,不在此语句中的代码也将执行。

让我们扩展上面的names.py程序,并创建一个名为more_names.py的新文件。在这个程序中,我们将声明一个全局变量,并修改我们原来的names()函数,使指令分为两个独立的函数。

第一个函数has_vowel()将检查name字符串是否包含元音字母。

第二个函数print_letters()将打印name字符串的每个字母。

more_names.py
# 声明全局变量name以供所有函数使用
name = str(input('Enter your name: '))


# 定义函数以检查名称是否包含元音字母
def has_vowel():
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')


# 迭代名称字符串中的字母
def print_letters():
    for letter in name:
        print(letter)

有了这个设置,让我们定义main()函数,其中将调用has_vowel()print_letters()函数。

more_names.py
# 声明全局变量name以供所有函数使用
name = str(input('Enter your name: '))


# 定义函数以检查名称是否包含元音字母
def has_vowel():
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')


# 迭代名称字符串中的字母
def print_letters():
    for letter in name:
        print(letter)


# 定义调用其他函数的主要方法
def main():
    has_vowel()
    print_letters()

最后,我们将在文件底部添加if __name__ == '__main__': 结构。 对于我们的目的,由于我们已经将所有希望执行的函数放在main() 函数中,因此我们将在此if 语句后调用main() 函数。

more_names.py
# 声明全局变量名称以在所有函数中使用
name = str(input('Enter your name: '))


# 定义函数以检查名称是否包含元音
def has_vowel():
    if set('aeiou').intersection(name.lower()):
        print('Your name contains a vowel.')
    else:
        print('Your name does not contain a vowel.')


# 遍历名称字符串中的字母
def print_letters():
    for letter in name:
        print(letter)


# 定义调用其他函数的主方法
def main():
    has_vowel()
    print_letters()


# 执行 main() 函数
if __name__ == '__main__':
    main()

现在我们可以运行程序:

  1. python more_names.py

程序将显示与names.py程序相同的输出,但这里的代码更有组织性,可以在不修改的情况下以模块化方式使用。

如果您不想声明一个main() 函数,您还可以这样结束程序:

more_names.py
...
if __name__ == '__main__':
    has_vowel()
    print_letters()

使用main() 作为一个函数和if __name__ == '__main__': 语句可以以逻辑方式组织您的代码,使其更易读和模块化。

结论

函数是程序中执行操作的代码块,有助于使我们的代码可重用和模块化。

要了解如何使您的代码更模块化,您可以阅读我们的指南:如何在Python 3中编写模块

Source:
https://www.digitalocean.com/community/tutorials/how-to-define-functions-in-python-3