**(双星/星号)和 *(星号/星号)在函数调用中意味着什么?

发布于 2024-09-03 08:32:08 字数 525 浏览 5 评论 0原文

zip(*x)f(**k) 等代码中,*** 的作用是什么> 分别是什么意思? Python 如何实现该行为,以及对性能有何影响?


另请参阅:将元组扩展为参数。请使用该问题来结束 OP 需要在参数上使用 * 并且不知道它存在的问题。同样,对于使用 ** 的情况,请使用 Converting Python dict to kwargs?

请参阅**(双星/星号)和*(星号/星号)对参数有什么作用?了解互补内容关于参数的问题。

In code like zip(*x) or f(**k), what do the * and ** respectively mean? How does Python implement that behaviour, and what are the performance implications?


See also: Expanding tuples into arguments. Please use that one to close questions where OP needs to use * on an argument and doesn't know it exists. Similarly, use Converting Python dict to kwargs? for the case of using **.

See What does ** (double star/asterisk) and * (star/asterisk) do for parameters? for the complementary question about parameters.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

唱一曲作罢 2024-09-10 08:32:08

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

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

A single star * unpacks a sequence or collection into positional arguments. Suppose we have

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

values = (1, 2)

Using the * unpacking operator, we can write s = add(*values), which will be equivalent to writing s = add(1, 2).

The double star ** does the same thing for a dictionary, providing values for named arguments:

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

Both operators can be used for the same function call. For example, given:

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

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

then s = add(*values1, **values2) is equivalent to s = sum(1, 2, c=10, d=15).

See also the relevant section of the tutorial in the Python documentation.


Similarly, * and ** can be used for parameters. Using * allows a function to accept any number of positional arguments, which will be collected into a single parameter:

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

Now when the function is called like s = add(1, 2, 3, 4, 5), values will be the tuple (1, 2, 3, 4, 5) (which, of course, produces the result 15).

Similarly, a parameter marked with ** will receive a dict:

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

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

this allows for specifying a large number of optional parameters without having to declare them.

Again, both can be combined:

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
何其悲哀 2024-09-10 08:32:08

在函数调用中,单星将列表转换为单独的参数(例如,给定 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}< /代码>)”。

In a function call, the single star turns a list into separate arguments (e.g. zip(*x) is the same as zip(x1, x2, x3) given x=[x1,x2,x3]) and the double star turns a dictionary into separate keyword arguments (e.g. f(**k) is the same as f(x=my_x, y=my_y) given k = {'x':my_x, 'y':my_y}.

In a function definition, it's the other way around: the single star turns an arbitrary number of arguments into a list, and the double start turns an arbitrary number of keyword arguments into a dictionary. E.g. def foo(*x) means "foo takes an arbitrary number of arguments and they will be accessible through x (i.e. if the user calls foo(1,2,3), x will be (1, 2, 3))" and def bar(**k) means "bar takes an arbitrary number of keyword arguments and they will be accessible through k (i.e. if the user calls bar(x=42, y=23), k will be {'x': 42, 'y': 23})".

李白 2024-09-10 08:32:08

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

例如,假设我对函数“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(test[0], test[1]) 之类的操作之外,没有其他方法可以调用 add ,这很丑。另外,如果变量的数量可变,那么代码可能会因为您需要的所有 if 语句而变得非常难看。

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

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

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

I find this particularly useful for storing arguments for a function call.

For example, suppose I have some unit tests for a function '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)

There is no other way to call add, other than manually doing something like add(test[0], test[1]), which is ugly. Also, if there are a variable number of variables, the code could get pretty ugly with all the if-statements you would need.

Another place this is useful is for defining Factory objects (objects that create objects for you).
Suppose you have some class Factory, that makes Car objects and returns them.
You could make it so that myFactory.make_car('red', 'bmw', '335ix') creates Car('red', 'bmw', '335ix'), then returns it.

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

This is also useful when you want to call the constructor of a superclass.

埋情葬爱 2024-09-10 08:32:08

它被称为扩展调用语法。来自文档

如果语法*表达式出现在函数调用中,则表达式的计算结果必须为序列。该序列中的元素被视为附加位置参数;如果有位置参数 x1,..., xN,并且表达式计算结果为序列 y1, ..., yM,则这相当于使用 M+N 位置参数 x1, ..., xN, y1, 的调用。 ..,yM。

和:

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

It is called the extended call syntax. From the documentation:

If the syntax *expression appears in the function call, expression must evaluate to a sequence. Elements from this sequence are treated as if they were additional positional arguments; if there are positional arguments x1,..., xN, and expression evaluates to a sequence y1, ..., yM, this is equivalent to a call with M+N positional arguments x1, ..., xN, y1, ..., yM.

and:

If the syntax **expression appears in the function call, expression must evaluate to a mapping, the contents of which are treated as additional keyword arguments. In the case of a keyword appearing in both expression and as an explicit keyword argument, a TypeError exception is raised.

黑色毁心梦 2024-09-10 08:32:08

当定义可能有许多具有相同值的键的字典时,它也很有用。例如,

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

可以写成,

d = {**dict.fromkeys(['a','b','c'],'r1'),'d':'r2'}

It is also useful when defining a dictionary that may have many keys with the same value. For Example,

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

can be written,

d = {**dict.fromkeys(['a','b','c'],'r1'),'d':'r2'}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文