繁体   English   中英

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

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

任何人都可以解释使用单星号或双星号打开字典时的区别吗? 您可以在函数参数中使用它们时提及它们的区别,前提是它与此处相关,我不这么认为。

但是,可能存在一些相关性,因为它们共享相同的星号语法。

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? 

此外,为什么在这种情况下作为函数参数传递时字典的键不允许是非字符串? 有什么例外吗? 为什么他们以这种方式设计Python,是因为编译器无法推断出这里的类型还是什么?

谢谢!

当字典被迭代为列表时,迭代会获取它的键,例如

for key in tmp:
    print(key)

是相同的

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

在这种情况下,解包为*tmp等效于*tmp.keys() ,忽略值。 如果你想使用这些值,你可以使用*tmp.values()

双星号用于定义带有关键字参数的函数时,例如

def foo(a, b):

或者

def foo(**kwargs):

在这里,您可以将参数存储在字典中并将其作为**tmp传递。 在第一种情况下,键必须是带有函数公司中定义的参数名称的字符串。 在第二种情况下,您可以将kwargs用作函数内的字典。

def foo(a,b)
   return a+b

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

在这种情况下:
foo(*tmp)表示foo(1, 3)
foo(**tmp)表示foo(1=2, 3=4) ,这将引发错误,因为1不能作为参数。 Arg 必须是字符串并且(感谢@Alexander Reynolds 指出这一点)必须以下划线或字母字符开头。 参数必须是有效的 Python 标识符。 这意味着你甚至不能做这样的事情:

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

或者

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

有关更多详细信息,请参阅python_basic_syntax

这是一个扩展的可迭代解包

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

对于单个 *,

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

在这里了解更多。

我认为函数参数和解包字典中的**双星号直观地表示这种方式:

#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])

现在所有的语法都有意义了。 单个星号也是如此。 唯一值得注意的是,如果你使用单个星号解包字典,你实际上是在尝试以列表的方式解包,并且只有字典的键被解包。

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

这样做的结果是,尽管 *expression 语法可能出现在显式关键字参数之后,但它在关键字参数(以及任何 **expression 参数 - 见下文)之前处理。 所以:

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