简体   繁体   English

在 Python 中解包字典时,单(非双)星号 * 是什么意思?

[英]What does single(not double) asterisk * means when unpacking dictionary in Python?

Can anyone explain the difference when unpacking the dictionary using single or double asterisk?任何人都可以解释使用单星号或双星号打开字典时的区别吗? You can mention their difference when used in function parameters, only if it is relevant here, which I don't think so.您可以在函数参数中使用它们时提及它们的区别,前提是它与此处相关,我不这么认为。

However, there may be some relevance, because they share the same asterisk syntax.但是,可能存在一些相关性,因为它们共享相同的星号语法。

def foo(a,b)
    return a+b

tmp = {1:2,3:4}
foo(*tmp)        #you get 4
foo(**tmp)       #typeError: keyword should be string. Why it bothers to check the type of keyword? 

Besides, why the key of dictionary is not allowed to be non-string when passed as function arguments in THIS situation?此外,为什么在这种情况下作为函数参数传递时字典的键不允许是非字符串? Are there any exceptions?有什么例外吗? Why they design Python in this way, is it because the compiler can't deduce the types in here or something?为什么他们以这种方式设计Python,是因为编译器无法推断出这里的类型还是什么?

Thanks!谢谢!

When dictionaries are iterated as lists the iteration takes the keys of it, for example当字典被迭代为列表时,迭代会获取它的键,例如

for key in tmp:
    print(key)

is the same as是相同的

for key in tmp.keys():
    print(key)

in this case, unpacking as *tmp is equivalent to *tmp.keys() , ignoring the values.在这种情况下,解包为*tmp等效于*tmp.keys() ,忽略值。 If you want to use the values you can use *tmp.values() .如果你想使用这些值,你可以使用*tmp.values()

Double asterisk is used for when you define a function with keyword parameters such as双星号用于定义带有关键字参数的函数时,例如

def foo(a, b):

or或者

def foo(**kwargs):

here you can store the parameters in a dictionary and pass it as **tmp .在这里,您可以将参数存储在字典中并将其作为**tmp传递。 In the first case keys must be strings with the names of the parameter defined in the function firm.在第一种情况下,键必须是带有函数公司中定义的参数名称的字符串。 And in the second case you can work with kwargs as a dictionary inside the function.在第二种情况下,您可以将kwargs用作函数内的字典。

def foo(a,b)
   return a+b

tmp = {1:2,3:4}
foo(*tmp)        #you get 4
foo(**tmp) 

In this case:在这种情况下:
foo(*tmp) mean foo(1, 3) foo(*tmp)表示foo(1, 3)
foo(**tmp) mean foo(1=2, 3=4) , which will raise an error since 1 can't be an argument. foo(**tmp)表示foo(1=2, 3=4) ,这将引发错误,因为1不能作为参数。 Arg must be strings and (thanks @ Alexander Reynolds for pointing this out) must start with underscore or alphabetical character. Arg 必须是字符串并且(感谢@Alexander Reynolds 指出这一点)必须以下划线或字母字符开头。 An argument must be a valid Python identifier.参数必须是有效的 Python 标识符。 This mean you can't even do something like this:这意味着你甚至不能做这样的事情:

def foo(1=2, 3=4):
   <your code>

or或者

def foo('1'=2, '3'=4):
   <your code>

See python_basic_syntax for more details.有关更多详细信息,请参阅python_basic_syntax

It is a Extended Iterable Unpacking .这是一个扩展的可迭代解包

>>> def add(a=0, b=0):
...     return a + b
...
>>> d = {'a': 2, 'b': 3}
>>> add(**d)#corresponding to add(a=2,b=3)
5

For single *,对于单个 *,

def add(a=0, b=0):
    ...     return a + b
    ...
    >>> d = {'a': 2, 'b': 3}
    >>> add(*d)#corresponding to add(a='a',b='b')
    ab

Learn more here . 在这里了解更多。

I think the ** double asterisk in function parameter and unpacking dictionary means intuitively in this way:我认为函数参数和解包字典中的**双星号直观地表示这种方式:

#suppose you have this function
def foo(a,**b):
    print(a)
    for x in b:
        print(x,"...",b[x])
#suppose you call this function in the following form
foo(whatever,m=1,n=2)   
#the m=1 syntax actually means assign parameter by name, like foo(a = whatever, m = 1, n = 2)
#so you can also do foo(whatever,**{"m":1,"n":2})
#the reason for this syntax is you actually do
**b is m=1,n=2 #something like pattern matching mechanism
so b is {"m":1,"n":2}, note "m" and "n" are now in string form
#the function is actually this:
def foo(a,**b):  # b = {"m":1,"n":2}
    print(a)
    for x in b:  #for x in b.keys(), thanks to @vlizana answer
        print(x,"...",b[x])

All the syntax make sense now.现在所有的语法都有意义了。 And it is the same for single asterisk.单个星号也是如此。 It is only worth noting that if you use single asterisk to unpack dictionary, you are actually trying to unpack it in a list way, and only key of dictionary are unpacked.唯一值得注意的是,如果你使用单个星号解包字典,你实际上是在尝试以列表的方式解包,并且只有字典的键被解包。

[https://docs.python.org/3/reference/expressions.html#calls] [https://docs.python.org/3/reference/expressions.html#calls]

A consequence of this is that although the *expression syntax may appear after explicit keyword arguments, it is processed before the keyword arguments (and any **expression arguments – see below).这样做的结果是,尽管 *expression 语法可能出现在显式关键字参数之后,但它在关键字参数(以及任何 **expression 参数 - 见下文)之前处理。 So:所以:

def f(a, b):
print(a, b)

f(b=1, *(2,))
f(a=1, *(2,))
#Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
#TypeError: f() got multiple values for keyword argument 'a'
f(1, *(2,))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM