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

2024-11-20 08:43:00
admin
原创
9
摘要:问题描述: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'}
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用