在函数调用中 **(双星号)和 *(星号)是什么意思?

2024-11-20 08:43:00
admin
原创
138
摘要:问题描述:zip(*x)在或这样的代码中,和分别f(**k)是什么意思? Python 如何实现该行为?性能影响是什么?*`**`另请参阅:将元组扩展为参数。请使用该选项关闭 OP 需要*在参数上使用但不知道其存在的问题。类似地,对于使用的情况,请使用将 Python 字典转换为 kwargs?。**有关参数...

问题描述:

zip(*x)在或这样的代码中,和分别f(**k)是什么意思? Python 如何实现该行为?性能影响是什么?*`**`


另请参阅:将元组扩展为参数。请使用该选项关闭 OP 需要*在参数上使用但不知道其存在的问题。类似地,对于使用的情况,请使用将 Python 字典转换为 kwargs?。**

有关参数的补充问题,请参阅*(双星号)和 (星号)对参数有何作用?


解决方案 1:

单个星号*将序列或集合解包为位置参数。假设我们有

def add(a, b):
    return a + b

values = (1, 2)

使用*解包运算符,我们可以写s = add(*values),这相当于写s = add(1, 2)

双星号**对字典起着同样的作用,为命名参数提供值:

values = {'a': 1, 'b': 2}
s = add(**values) # equivalent to add(a=1, b=2)

两个运算符都可以用于同一个函数调用。例如,给定:

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = {'c': 10, 'd': 15}

s = add(*values1, **values2)相当于s = sum(1, 2, c=10, d=15)

另请参阅Python 文档中本教程的相关部分。


类似地,***可用于参数。使用*允许函数接受任意数量的位置参数,这些参数将被收集到单个参数中:

def add(*values):
    s = 0
    for v in values:
        s = s + v
    return s

现在,当像 这样的函数被调用时s = add(1, 2, 3, 4, 5)values将是元组(1, 2, 3, 4, 5)(当然,它会产生结果15)。

类似地,标有 的参数**将收到dict

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

这允许指定大量可选参数而无需声明它们。

同样,两者可以结合起来:

def add(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = add(1, 2, 3, 4, 5)            # returns 15
s = add(1, 2, 3, 4, 5, neg=True)  # returns -15
s = add(1, 2, 3, 4, 5, neg=False) # returns 15

解决方案 2:

在函数调用中,单星号将列表转换为单独的参数(例如与给定zip(*x)的相同),双星号将字典转换为单独的关键字参数(例如与给定的相同)。zip(x1, x2, x3)`x=[x1,x2,x3]f(**k)f(x=my_x, y=my_y)`k = {'x':my_x, 'y':my_y}

在函数定义中,情况正好相反:单星号将任意数量的参数转换为列表,双星号将任意数量的关键字参数转换为字典。例如,def foo(*x)表示“foo 接受任意数量的参数,并且可以通过 访问它们x(即,如果用户调用foo(1,2,3)x则为(1, 2, 3))”,而def bar(**k)表示“bar 接受任意数量的关键字参数,并且可以通过 访问它们k(即,如果用户调用bar(x=42, y=23)k则为{'x': 42, 'y': 23})”。

解决方案 3:

我发现这对于存储函数调用的参数特别有用。

例如,假设我对函数“add”有一些单元测试:

def add(a, b):
    return a + b

tests = { (1,4):5, (0, 0):0, (-1, 3):3 }

for test, result in tests.items():
    print('test: adding', test, '==', result, '---', add(*test) == result)

除了手动执行类似 的操作(这很丑陋)之外,没有其他方法可以调用 add add(test[0], test[1])。此外,如果变量数量可变,代码可能会变得非常丑陋,因为您需要所有 if 语句。

另一个有用的地方是定义 Factory 对象(为您创建对象的对象)。假设您有一个 Factory 类,它创建 Car 对象并返回它们。您可以让它myFactory.make_car('red', 'bmw', '335ix')创建Car('red', 'bmw', '335ix'),然后返回它。

def make_car(*args):
    return Car(*args)

当你想要调用超类的构造函数时这也很有用。

解决方案 4:

这被称为扩展调用语法。摘自文档:

如果语法 *expression 出现在函数调用中,expression 必须求值为一个序列。该序列中的元素被视为附加位置参数;如果有位置参数 x1,..., xN,并且 expression 求值为序列 y1, ..., yM,则这相当于具有 M+N 个位置参数 x1, ..., xN, y1, ..., yM 的调用。

和:

如果语法 **expression 出现在函数调用中,则 expression 必须求值为映射,其内容将被视为附加关键字参数。如果关键字同时出现在 expression 中和作为显式关键字参数,则会引发 TypeError 异常。

解决方案 5:

在定义可能包含多个具有相同值的键的字典时,它也很有用。例如,

d = {'a':'r1', 'b':'r1','c':'r1','d':'r2'}

可以写成,

d = {**dict.fromkeys(['a','b','c'],'r1'),'d':'r2'}
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1120  
  IPD(Integrated Product Development,集成产品开发)流程是一种广泛应用于高科技和制造业的产品开发方法论。它通过跨职能团队的紧密协作,将产品开发周期缩短,同时提高产品质量和市场成功率。在IPD流程中,CDCP(Concept Decision Checkpoint,概念决策检查点)是一个关...
IPD培训课程   75  
  研发IPD(集成产品开发)流程作为一种系统化的产品开发方法,已经在许多行业中得到广泛应用。它不仅能够提升产品开发的效率和质量,还能够通过优化流程和资源分配,显著提高客户满意度。客户满意度是企业长期成功的关键因素之一,而IPD流程通过其独特的结构和机制,能够确保产品从概念到市场交付的每个环节都围绕客户需求展开。本文将深入...
IPD流程   66  
  IPD(Integrated Product Development,集成产品开发)流程是一种以跨职能团队协作为核心的产品开发方法,旨在通过优化资源分配、提高沟通效率以及减少返工,从而缩短项目周期并提升产品质量。随着企业对产品上市速度的要求越来越高,IPD流程的应用价值愈发凸显。通过整合产品开发过程中的各个环节,IPD...
IPD项目管理咨询   76  
  跨部门沟通是企业运营中不可或缺的一环,尤其在复杂的产品开发过程中,不同部门之间的协作效率直接影响项目的成败。集成产品开发(IPD)作为一种系统化的项目管理方法,旨在通过优化流程和增强团队协作来提升产品开发的效率和质量。然而,跨部门沟通的复杂性往往成为IPD实施中的一大挑战。部门之间的目标差异、信息不对称以及沟通渠道不畅...
IPD是什么意思   70  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用