函数调用

一个可调用对象是一个可以接受一些参数(也叫做实参)并可能返回一个对象(通常是包含多个对象的元组)的对象。

在 Python 中,函数是最简单的可调用对象,但还有其他型的可调用对象,例如或某些的实例。

定义函数

在 Python 中,函数的定义遵循以下格式:

def functionname(arg1, arg2, ...):
    statement1
    statement2
    ...

例如:

def functionname(arg1, arg2):
    return arg1 + arg2

调用该函数:

t = functionname(24, 24)  # 结果:48

如果一个函数不接受任何参数,它仍然需要包括括号,但括号内什么也不放:

def functionname():
    statement1
    statement2
    ...

函数定义中的参数将调用时传递的实参(即函数被调用时传递的值)绑定到函数定义时给定的名称,这些名称称为形式参数。函数体内部对实际参数的名称没有任何了解,实际参数的名称可能甚至不可访问(它们可能位于另一个函数内部)。

一个函数可以“返回”一个值,例如:

def square(x):
    return x * x

一个函数可以在函数体内定义局部变量,这些变量仅对该函数“可见”。局部变量和参数一起构成了函数作用域内的所有变量。函数返回或达到函数体的结尾时,所有变量都会失去绑定。

你可以像下面这样返回多个值:

def first2items(list1):
    return list1[0], list1[1]

a, b = first2items(["Hello", "world", "hi", "universe"])
print(a + " " + b)

声明参数

当调用一个函数并传递值进行进一步处理时,我们需要将一些值作为函数参数传递。例如:

def find_max(a, b):
    if a > b:
        return str(a) + " is greater than " + str(b)
    elif b > a:
        return str(b) + " is greater than " + str(a)

find_max(30, 45)  # 这里 (30, 45) 是用于查找这两个数的最大值的参数

输出将是:

45 is greater than 30

默认参数值

如果函数定义中的任何形式参数使用 "arg = value" 的格式声明,那么在调用函数时,你可以选择不为这些参数指定值。如果不指定值,那么该参数将使用定义时给定的默认值。

def display_message(message, truncate_after=4):
    print(message[:truncate_after])

display_message("message")
# 输出: mess

display_message("message", 6)
# 输出: messag

可变长度的参数列表

Python 允许你声明两个特殊的参数,这些参数允许你创建任意长度的参数列表。这意味着每次调用函数时,你可以指定任意数量的参数,超出一定数量的参数。

def function(first, second, *remaining):
    statement1
    statement2
    ...

调用上述函数时,你必须为前两个参数提供值。然而,由于第三个参数带有星号(*),所以任何在前两个参数之后的实参都会被打包成元组,并绑定到 remaining 上。

def print_tail(first, *tail):
    print(tail)

print_tail(1, 5, 2, "omega")
# 输出: (5, 2, 'omega')

如果我们声明一个形式参数,前面加上两个星号(**),那么它将绑定到一个字典,包含所有不对应于任何形式参数的实际参数中的关键字参数。例如,考虑以下函数:

def make_dictionary(max_length=10, **entries):
    return dict([(key, entries[key]) for i, key in enumerate(entries.keys()) if i < max_length])

如果我们调用这个函数并传入除 max_length 以外的任何关键字参数,它们将被放入字典 entries 中。如果我们包括 max_length 关键字参数,它将绑定到 max_length 形式参数上,像往常一样。

make_dictionary(max_length=2, key1=5, key2=7, key3=9)
# 输出: {'key3': 9, 'key2': 7}

按值传递和按引用传递

作为参数传递给函数的对象是通过引用传递的;它们不会被复制。因此,传递一个大型列表作为参数并不会将所有成员复制到内存中的新位置。注意,即使是整数也是对象。然而,在一些其他编程语言中,按值和按引用的区别通常用于区分被调用的函数是否能实际改变传递的参数,以及调用函数是否能看到这些更改。

传递的可变型的对象(例如列表和字典)可以被被调用的函数修改,这些修改在调用函数中是可见的。而传递的不可变型的对象(例如整数和字符串)不能被被调用的函数修改;调用函数可以确定被调用的函数不会修改它们。有关可变性,请参见数据类型章节。

函数调用

一个可调用对象是一个可以接受一些参数(也叫做实参)并可能返回一个对象(通常是包含多个对象的元组)的对象。

在 Python 中,函数是最简单的可调用对象,但也有其他型的可调用对象,如或某些的实例。

定义函数

在 Python 中,函数的定义遵循以下格式:

def functionname(arg1, arg2, ...):
    statement1
    statement2
    ...

例如:

def functionname(arg1, arg2):
    return arg1 + arg2

调用该函数:

t = functionname(24, 24)  # 结果:48

如果函数不接受任何参数,它仍然需要括号,但括号内没有内容:

def functionname():
    statement1
    statement2
    ...

函数定义中的参数会将调用时传递的实参(即函数调用时的参数)绑定到定义时给定的名称,这些名称称为形式参数。函数体内部对实际参数的名称没有任何了解,实际参数的名称可能甚至不可访问(它们可能位于另一个函数内部)。

一个函数可以“返回”一个值,例如:

def square(x):
    return x * x

一个函数可以在函数体内定义局部变量,这些变量仅对该函数“可见”。局部变量与参数一起构成了函数作用域内的所有变量。函数返回或达到函数体的结尾时,所有变量都会失去绑定。

你可以像下面这样返回多个值:

def first2items(list1):
    return list1[0], list1[1]

a, b = first2items(["Hello", "world", "hi", "universe"])
print(a + " " + b)

声明参数

当调用一个函数并传递值进行进一步处理时,我们需要将一些值作为函数参数传递。例如:

def find_max(a, b):
    if a > b:
        return str(a) + " is greater than " + str(b)
    elif b > a:
        return str(b) + " is greater than " + str(a)

find_max(30, 45)  # 这里 (30, 45) 是用于查找这两个数的最大值的参数

输出将是:

45 is greater than 30

默认参数值

如果函数定义中的任何形式参数使用 "arg = value" 的格式声明,那么在调用函数时,你可以选择不为这些参数指定值。如果不指定值,那么该参数将使用定义时给定的默认值。

def display_message(message, truncate_after=4):
    print(message[:truncate_after])

display_message("message")
# 输出: mess

display_message("message", 6)
# 输出: messag

可变长度的参数列表

Python 允许你声明两个特殊的参数,这些参数允许你创建任意长度的参数列表。这意味着每次调用函数时,你可以指定任意数量的参数,超出一定数量的参数。

def function(first, second, *remaining):
    statement1
    statement2
    ...

调用上述函数时,你必须为前两个参数提供值。然而,由于第三个参数带有星号(*),所以任何在前两个参数之后的实参都会被打包成元组,并绑定到 remaining 上。

def print_tail(first, *tail):
    print(tail)

print_tail(1, 5, 2, "omega")
# 输出: (5, 2, 'omega')

如果我们声明一个形式参数,前面加上两个星号(**),那么它将绑定到一个字典,包含所有不对应于任何形式参数的实际参数中的关键字参数。例如,考虑以下函数:

def make_dictionary(max_length=10, **entries):
    return dict([(key, entries[key]) for i, key in enumerate(entries.keys()) if i < max_length])

如果我们调用这个函数并传入除 max_length 以外的任何关键字参数,它们将被放入字典 entries 中。如果我们包括 max_length 关键字参数,它将绑定到 max_length 形式参数上,像往常一样。

make_dictionary(max_length=2, key1=5, key2=7, key3=9)
# 输出: {'key3': 9, 'key2': 7}

按值传递和按引用传递

作为参数传递给函数的对象是通过引用传递的;它们不会被复制。因此,传递一个大型列表作为参数并不会将所有成员复制到内存中的新位置。注意,即使是整数也是对象。然而,在一些其他编程语言中,按值和按引用的区别通常用于区分被调用的函数是否能实际改变传递的参数,以及调用函数是否能看到这些更改。

传递的可变型的对象(例如列表和字典)可以被被调用的函数修改,这些修改在调用函数中是可见的。而传递的不可变型的对象(例如整数和字符串)不能被被调用的函数修改;调用函数可以确定被调用的函数不会修改它们。有关可变性,请参见数据类型章节。

最后修改: 2025年01月31日 星期五 00:19