这是关于首次出现在 Python 3.x 版本中的功能系列文章的第一篇。Python 3.0 于 2008 年首次发布,即使已经发布了一段时间,它引入的许多功能仍未被充分利用且非常酷。以下是您应该了解的三个功能。
仅限关键字参数
Python 3.0 首次引入了仅限关键字参数的概念。在此之前,不可能指定一个 API,其中某些参数只能通过关键字传入。这在具有许多参数的函数中很有用,其中一些参数可能是可选的。
考虑一个人为的例子
def show_arguments(base, extended=None, improved=None, augmented=None):
print("base is", base)
if extended is not None:
print("extended is", extended)
if improved is not None:
print("improved is", improved)
if augmented is not None:
print("augmented is", augmented)
当阅读调用此函数的代码时,有时很难理解发生了什么
show_arguments("hello", "extra")
base is hello
extended is extra
show_arguments("hello", None, "extra")
base is hello
improved is extra
虽然可以使用关键字参数调用此函数,但并不明显这是最佳方式。相反,您可以将这些参数标记为仅限关键字
def show_arguments(base, *, extended=None, improved=None, augmented=None):
print("base is", base)
if extended is not None:
print("extended is", extended)
if improved is not None:
print("improved is", improved)
if augmented is not None:
print("augmented is", augmented)
现在,您不能使用位置参数传入额外的参数
show_arguments("hello", "extra")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-6000400c4441> in <module>
----> 1 show_arguments("hello", "extra")
TypeError: show_arguments() takes 1 positional argument but 2 were given
对函数的有效调用更容易预测
show_arguments("hello", improved="extra")
base is hello
improved is extra
nonlocal
有时,函数式编程人员会根据编写累加器的容易程度来判断一种语言。累加器是一个函数,调用时返回到目前为止发送给它的所有参数的总和。
Python 3.0 之前的标准答案是
class _Accumulator:
def __init__(self):
self._so_far = 0
def __call__(self, arg):
self._so_far += arg
return self._so_far
def make_accumulator():
return _Accumulator()
虽然承认有点冗长,但这确实有效
acc = make_accumulator()
print("1", acc(1))
print("5", acc(5))
print("3", acc(3))
此代码的输出将是
1 1
5 6
3 9
在 Python 3.x 中,nonlocal 可以用明显更少的代码实现相同的行为。
def make_accumulator():
so_far = 0
def accumulate(arg):
nonlocal so_far
so_far += arg
return so_far
return accumulate
虽然累加器是人为的例子,但使用 nonlocal
关键字来拥有具有状态的内部函数是一个强大的工具。
扩展解构
假设您有一个 CSV 文件,其中每行包含多个元素
- 第一个元素是年份
- 第二个元素是月份
- 其他元素是该月发布的文章总数,每天一个条目
请注意,最后一个元素是文章总数,而不是每天发布的文章数。例如,一行可以以以下内容开头
2021,1,5,8,10
这意味着在 2021 年 1 月,第一天发布了五篇文章。第二天,又发布了三篇文章,总数达到 8 篇。第三天,又发布了两篇文章。
月份可能有 28、30 或 31 天。提取月份、日期和文章总数有多难?
在 Python 3.0 之前的版本中,您可能会编写类似这样的代码
year, month, total = row[0], row[1], row[-1]
这是正确的,但它掩盖了格式。使用扩展解构,可以用这种方式表达相同的内容
year, month, *rest, total = row
这意味着如果格式发生更改以添加前缀描述,您可以将代码更改为
_, year, month, *rest, total = row
无需为每个索引添加 1
。
下一步是什么?
Python 3.0 及其更高版本已经发布超过 12 年了,但它的一些功能仍未被充分利用。在本系列文章的下一篇中,我将介绍其中的另外三个。
评论已关闭。