一文带您精通Python 函数:全方位指南
函数是编程中最为基本的构建单元,它们在组织代码和实现功能方面发挥着核心作用。Python 语言以其灵活性而著称,这种灵活性体现在函数定义和调用上。例如,Python 函数参数没有强制的类型约束,仅通过类型提示提供建议,这使得函数的定义和使用更加自由,但也增加了复杂性。
在 Python 中,函数参数的定义与使用极具灵活性,但也因此带来了一定的复杂性。Python 支持四种主要类型的参数:正常参数(normal arguments)、默认参数(default arguments)、任意位置参数(arbitrary positional arguments)以及任意关键字参数(arbitrary keyword arguments)。这种灵活性虽然极大地增加了函数的适用范围和便利性,但也可能造成一定的障碍。
- 正常参数 是最常见的参数形式,它们在函数定义时明确列出,并且在调用函数时必须提供相应的值。
- 默认参数 允许在函数定义时为参数指定默认值,这使得调用函数时可以省略这些参数,但这也可能导致函数行为的不明确性。
- 任意位置参数(通常以 *args 表示)允许函数接受任意数量的位置参数,这种灵活性可能使得函数的接口变得难以理解和使用。
- 任意关键字参数(通常以 **kwargs 表示)使得函数能够接受任意数量的关键字参数,这种特性虽然增强了函数的灵活性,但也增加了参数处理的复杂度。
这些参数类型虽然提供了强大的功能,但也可能使函数定义和调用变得复杂。在本文中,我们将详细探讨这些参数的特点与使用技巧,帮助您在充分利用 Python 函数灵活性的同时,减少可能遇到的障碍。
1.函数中的类型提示(Type hinting)
说实在的,我写过Python代码中,其实很少使用类型提示。为阅读和生成help 文档方便还是要认真编写类型提示和文档字符串的。
def avg(a: int,b: int)-> float:
"""
Finds average of a and b
Args:
a(int): an integer
b(int):an integer
Returns:
(float):average of a and b
"""
return (a+b)/2
print(avg(1,2))
- a: int 表示理想情况下a应该是一个整数
- b: int表示b理想情况下应该是一个整数
- -> float表示该函数理想情况下应该返回一个浮点值
类型提示只是提示,并不强制语法约束。如果将字符串或其他数据类型传入a和b, Python 实际上是可以接受的(直到它尝试将字符串除以 2 导致错误)
类型提示的目的更多是使代码更易于人类阅读和 IDE(例如 PyCharm 或 VSCode)能够为您进行检查。
2.默认参数(Default arguments)
def greet(name,greeting ='hi'):
print(f"{greeting} {name}")
在上面的示例函数中,greeting='hi'是一个默认参数。
- 如果不向greeting传递任何内容,则会自动赋值“hi”
- 如果决定将某些内容传递给 greeting,它将采用该值
def greet(name,greeting ='hi'):
print(f"{greeting} {name}")
greet("john")
greet("john",greeting="hello")
greet("john","HELLO")
如果函数中有大量参数,并且不希望每次调用该函数时都必须传递每个参数,那么这很有用。
3.参数和实参 Arguments VS Parameters
假设我们有一个简单的函数,它接受两个参数(Argument)(a 和 b)并返回它们的平均值。
- 参数(Argument) 是在定义函数时写在括号内的变量。在下面的例子中,a 和 b 是参数。
- 实参(Parameter) 是在调用函数时实际传递给函数的值。在下面的例子中,当我们调用 avg(a, b) 函数时,2和 4 是实参。
def avg(a,b): # a b 是参数 Arguments
return (a+b)/2
x=avg(2,4) # 3,4 是实参 Parameters
print(x)
4.位置参数和关键字参数(Positional VS Keyword Arguments)
def avg(a,b):
print(f"{a=}",f"{b=}")
return (a+b)/2
avg(4,7)
4 和 7 是位置参数(positional arguments)。位置参数需要按照顺序传递——4 被传递给 a,而 7 被传递给 b。
def avg(a,b):
print(f"{a=}",f"{b=}")
return (a+b)/2
avg(b=5,a=8)
b=5 和 a=8 是关键字参数(keyword arguments)。关键字参数不需要按顺序传递,但必须使用 key=value 的格式传递。
5.任意位置参数 (*args)(Arbitrary Positional Arguments )
函数中的任意位置参数(Arbitrary positional arguments),也称为 *args,允许函数接受任意数量的位置参数。
def test(*args):
print(args)
test()
test(1)
test(1,2)
test(1,2,3)
test(1,2,3,4)
test 函数接受 *args,这允许函数接收任意数量的位置参数,这些参数会被收集到一个名为 args 的元组中。
可以将 *args 与正常参数结合使用,但 *args 必须放在正常参数之后:
def test(a,b,*args):
print(f"{a=} {b=}",args)
try:
test()
except Exception as e:
print(e)
try:
test(1)
except Exception as e:
print(e)
test(1,2)
test(1,2,3)
test(1,2,3,4)
PS:不一定要用 *args 这个名字。只要在参数名前加上 *,可以使用任何名称。
6.任意关键字参数 (kwargs)( Arbitrary keyword arguments )
任意关键字参数,也称为 **kwargs,允许我们的函数接收任意数量的关键字参数。
def test(**kwargs):
print(kwargs)
test()
test(a=1)
test(b=2,a=1)
test 函数接受 **kwargs,这允许函数接收任意数量的关键字参数,这些参数会被收集到一个名为 kwargs 的字典中。
也可以将 **kwargs 与正常参数结合使用,但 **kwargs 必须放在正常参数之后:
def test(a,b,**kwargs):
print(f"{a=} {b=}",kwargs)
try:
test()
except Exception as e:
print(e)
try:
test(a=1)
except Exception as e:
print(e)
test(b=2,a=1)
test(b=2,a=1,c=3)
PS:不必非要将其命名为 kwargs。只要在参数名前加上 **,可以使用任何名称。
7.使用 * 和 ** 将列表/字典传递给函数
使用 * 将包含位置参数的列表传递给函数:
def print_args(*args):
print(args)
args_list = [1, 2, 3]
print_args(*args_list)
使用 ** 将包含关键字参数的字典传递给函数:
def print_kwargs(**kwargs):
print(kwargs)
kwargs_dict = {'a': 1, 'b': 2, 'c': 3}
print_kwargs(**kwargs_dict)
函数是编程的基本单元,Python 的灵活性体现在其函数参数的多样性上,包括正常参数、默认参数、任意位置参数(*args)和任意关键字参数(**kwargs)。虽然这些特性增加了函数的灵活性和便利性,但也带来了复杂性。例如,*args 允许接收任意数量的位置参数,而 **kwargs 允许接收任意数量的关键字参数。通过适当使用这些参数类型,函数的定义和调用可以变得更强大和灵活,同时也需要注意参数的正确顺序和名称。