4.7 KiB
Python 函数:高级概念
您知道如何强制关键字参数、创建函数装饰器、创建匿名函数或者将数组或字典解包到函数的参数中吗?在这篇 Python 函数高级概念的文章中,我们将讨论一些围绕函数的更高级的概念。我将这些放在一篇单独的文章中,因为我不想让初学者对这些概念感到困惑。
你可能想先阅读我们对 Python 函数的介绍。
目录
强制关键字参数
关键字参数有许多优点:
- 你没有被强迫按照特定的顺序来提供你的论点——名字很重要,而不是立场。
- 关键字参数提供了清晰度。不用查函数本身,你通常可以通过看名字猜出参数的用途。
那很好,但是你可能已经知道这些事情了。您可能不知道的是,您还可以强制关键字参数。在 PEP 3202 中描述了细节,但是归结起来就是在想要强制作为关键字参数的参数前使用星号。或者,如下所示,在所有参数之前,强制所有参数都是关键字参数:
>>> def f(*, a, b):
... print(a, b)
...
>>> f(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() takes 0 positional
arguments but 2 were given
>>> f(a=1, b=2)
1 2
>>>
当您开发某种类型的库时,这个高级函数技巧可能会派上用场。也许你还不想坚持某个论点的顺序。在这种情况下,这是强制库的用户使用命名参数的方法,使顺序变得无关紧要。
使用*和**作为函数参数
有些函数需要很长的参数列表。虽然这应该完全避免,例如,通过使用数据类,但这并不总是由你决定。在这种情况下,第二个最好的选择是创建一个包含所有命名参数的字典,并将其传递给函数。这通常会使您的代码更具可读性。您可以通过使用前缀**来解包字典,以便与命名的关键字一起使用:
>>> def f(a, b):
... print(a, b)
...
>>> args = { "a": 1, "b": 2 }
>>> f(**args)
1 2
类似地,我们可以使用单个*来解包一个列表,并将其内容作为位置参数提供给一个函数:
>>> def f(a, b, c):
... print(a, b, c)
...
>>> l = [1, 2, 3]
>>> f(*l)
1 2 3
装饰您的功能
装饰器是一个函数的包装器,它以某种方式修改函数的行为。decorators 有许多用例,您可能以前在使用 Flask 这样的框架时使用过。
让我们创建自己的装饰器;它比你想象的要简单,也许有一天会派上用场:
def print_argument(func):
def wrapper(the_number):
print("Argument for", func.__name__, "is", the_number)
return func(the_number)
return wrapper
@print_argument
def add_one(x):
return x + 1
print(add_one(1))
在print_argument中,我们定义了一个包装函数。该函数打印被调用函数的参数和名称。接下来,它执行实际的函数并返回结果,就像函数被定期调用一样。使用@print_argument,我们将装饰器应用于一个函数。也许没有必要说:这个装饰器也可以在其他函数中重用。
我们的小脚本的输出将是:
Argument for add_one is 1
2
匿名函数
有时候,命名一个函数是不值得的。一个例子是当你确定函数只会被使用一次。对于这种情况,Python 为我们提供了匿名函数,也称为 lambda 函数。
lambda 函数可以赋给一个变量,从而创建了一种简洁的函数定义方式:
>>> add_one = lambda x: x + 1
>>> add_one(3)
4
当你需要使用一个函数作为参数时,这就变得更有趣了。在这种情况下,该函数通常只使用一次。如您所知,map将一个函数应用于一个可迭代对象的所有元素。我们可以在调用 map 时使用 lambda:
>>> numbers = [1, 2, 3, 4]
>>> times_two = map(lambda x: x * 2, numbers)
>>> list(times_two)
[2, 4, 6, 8]
>>>
事实上,这是一种你会经常看到的模式。当你需要对一个 iterable 对象的每个元素应用一个相对简单的操作时,结合 lambda 函数使用map()既简洁又高效。