Python中星号的5种用法

发布时间:2023年12月29日

Python中星号的5种用法(5 Uses of Asterisks in Python)


星号asterisk被称为乘法运算符multiplication operator,是所有程序中常用的符号。我们只需将其用作乘法运算符即可。但是,如果你真的想成为一名 Python 专家expert。是时候了解星号asterisk在 Python 中的作用useful和功能powerful了。

本篇文章将用最通俗易懂的例子,由浅入深地讲解星号的 5 种使用场景。

Use 1: 乘法Multiplication或幂Exponentiation运算符Operator

最简单的用法是利用星号asterisks作为中缀运算符infix operators:

  • 单个 * 用于乘法运算multiplication operation。
  • ** ,用于指数运算(也称为幂运算)exponentiation operation。
multiplication_operation = 2*3
print(multiplication_operation)  # 6
exponentiation_operation = 2**3
print(exponentiation_operation)  # 8

Use 2: 接收无限数量的参数

如果您需要更多的灵活性flexibility,甚至不确定将传递多少个参数arguments,那么函数并不一定要接收固定数量的参数arguments。下面是星号的表演时间asterisks’ showtime。

def print_genius(*names):
    print(type(names))
    for n in names:
        print(n)

print_genius('Elon Mask', 'Mark Zuckerberg ', 'Zhang San')
# <class 'tuple'>
# Elon Mask
# Mark Zuckerberg 
# Zhang San

def top_genius(**names):
    print(type(names))
    for k, v in names.items():
        print(k, v)

top_genius(Top1="Elon Mask", Top2="Mark Zuckerberg", Top3="Zhang San")
# <class 'dict'>
# Top1 Elon Mask
# Top2 Mark Zuckerberg
# Top3 Zhang San

正如上面的例子所示,当定义一个函数function时,我们可以定义前缀为一个或两个星号asterisks的参数parameter来捕获无限数量的参数arguments。

  • 以一个 * 为前缀的参数可以将任意多个位置参数positional arguments并入一个 tuple 中。
  • 以两个 * 为前缀的参数可以将任意数量的关键字参数keyword arguments捕捉到一个 dict 中。

按照惯例By convention,如果无法确定函数参数的个数,我们就定义如下函数:

def func(*args, **kwargs):
    pass

Use 3: 仅限关键字参数Keyword-Only Arguments

星号asterisks的一个很酷的用法是让函数function只能接收关键字参数keyword arguments。

一个例子胜过千言万语:

def genius(*, first_name, last_name):
    print(first_name, last_name)

# genius('Zhang','San')
# TypeError: genius() takes 0 positional arguments but 2 were given
genius(first_name='Zhang', last_name='San')
# Zhang San

如上例所示,只有一个 * 可以限制以后的所有参数必须以关键字参数keyword arguments进行传递。

实际上,如果我们只想限制一些参数arguments只能使用关键字keyword-only,而保留一些位置参数positional arguments。我们只需将位置参数positional arguments放在星号asterisk之前即可。

def genius(age, *, first_name, last_name):
    print(first_name, last_name, 'is', age)
genius(28, first_name='Zhang', last_name='San')
# Zhang San is 28

Use 4: 可迭代对象Iterables拆包Unpacking

我们可以使用星号asterisks来对可迭代对象Iterables进行拆包unpack,这将使我们的程序更加清晰和优雅。

例如,如果我们要将不同的可迭代对象Iterables(如一个列表list、一个元组tuple和一个集合set)组合成一个新的列表list,哪种方法最好?

当然,我们可以使用 for-loops 循环遍历所有项目,并将其逐一添加到新列表list中:

A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = []
for a in A:
    L.append(a)
for b in B:
    L.append(b)
for c in C:
    L.append(c)
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]

显然,这种方法可以完成我们的任务,但代码看起来很长,而且不太 “Pythonic”。

更好的方法是使用列表推导式list comprehensions:

A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = [a for a in A] + [b for b in B] + [c for c in C]
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]

我们将三个 for 循环简化为一行列表理解。这已经是 Pythonic 了,但不一定是最简单的!

是时候看看星号有多美了。

A = [1, 2, 3]
B = (4, 5, 6)
C = {7, 8, 9}
L = [*A, *B, *C]
print(L)
# [1, 2, 3, 4, 5, 6, 8, 9, 7]

如上所述,我们可以使用星号asterisk作为可迭代对象iterables的前缀来拆包unpack它们的项目items。

顺便说一下,如果我们使用单个 * 作为 dict 的前缀,其键keys将被拆包unpacked。

如果我们使用双星号 ** 作为前缀,那么其值values将被拆包unpacked。但是,我们必须使用它们的键keys来接收拆包unpacked后的值values。由于这种不便,用星号asterisks提取 dict 中的项items并不常见。

D = {'first': 1, 'second': 2, 'third': 3}

# 注意是3个参数
print(*D, sep="...")  # first...second...third

# print(**D)
# TypeError: 'first' is an invalid keyword argument for print()

print('{first},{second},{third}'.format(**D))  # 1,2,3

Use 5: 扩展可迭代对象Iterable的拆包

PEP 3132 引入了这种拆包语法,以使我们的代码更加优雅。

这个PEP提出了一种新的语法,允许我们在解包unpacking可迭代对象iterable时,使用一个“catch-all”名称来捕获所有未被分配给其他名称的项目items,并将它们存储在一个列表中。这样就可以更方便地处理不确定数量的项目items。

L = [1, 2, 3, 4, 5, 6, 7, 8]
a, *b = L
print(a)
# 1
print(b)
# [2, 3, 4, 5, 6, 7, 8]

官方翻译:本 PEP 提议修改可迭代解包语法,允许指定一个 “全包catch-all” 名称,该名称将被分配一个未分配给 “常规regular” 名称的所有项目的列表。

一个例子胜过千言万语An example says more than a thousand words:

a, *b, c = range(5)
print(a)  # 0
print(b)  # [1, 2, 3]
print(c)  # 4

结论

星号asterisk是程序中最常用的运算符operators之一。除了用作乘法运算符multiplication operator外,它在 Python 中还有一些优雅而强大elegant and powerful的用法,这将帮助我们的代码变得更加 “Pythonic”。

文章来源:https://blog.csdn.net/JENREY/article/details/135286298
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。