[英]python unpacking arg list with *args and **kwargs along with other positional and keyword only params
我在名为 kwargs.py 的文件中定义了以下 function。 (将模块更改为 unpacking.py 使 function 按预期工作)。 请参阅问题底部的图像。
def tag(name, *content, cls=None, **attrs):
if cls is not None:
attrs['class'] = cls
if attrs:
attr_str = ''.join(' %s="%s"' % (key,val)
for key, val
in sorted(attrs.items()))
else:
attr_str = ''
if content:
return '\n'.join('<%s%s>%s</%s>' % (name,attr_str,c,name) for c in content)
else:
return '<%s%s />' % (name,attr_str)
执行此操作时
tag('div', 'testing', cls='test', **dict(id=33,alt='this is a test'))
我得到的结果是
'<div alt="this is a test" class="test" id="33">testing</div>'
但是当我执行这个
tag(**dict(name='div', content=('testing','and testing'), cls='test', id=33, alt='this is a test'))
我只得到
'<div alt="this is a test" class="test" id="33" />'
为什么要分配参数name
但未分配content
。 (即使元组没有解包,我也希望至少元组本身被分配给 content[0])。
我在这里想念什么?
*content
不是论据。 你不能给它分配任何东西。
文档确实没有明确解释。 它只是一个可以在 function 主体中使用的变量。 它的作用是“收集所有剩余的输入参数”。
通常,这些可变参数 arguments 将在形式参数列表中排在最后,因为它们会收集传递给 function 的所有剩余输入 arguments。
https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists
本 function
def func(*args, **kwargs):
print("args", args)
print("kwargs", kwargs)
func(args=[1, 2, 3])
将打印
args ()
kwargs {'args': [1, 2, 3]}
编辑:
你的例子是错误的。 您无法获得不同的 output。
对于这个 function
def tag(name, *content, cls=None, **attrs):
if cls is not None:
attrs['class'] = cls
if attrs:
attr_str = ''.join(' %s="%s"' % (key, val)
for key, val
in sorted(attrs.items()))
else:
attr_str = ''
if content:
resp = '\n'.join('<%s%s>%s</%s>' % (name, attr_str, c, name) for c in content)
else:
resp = '<%s%s />' % (name, attr_str)
print("name", name)
print("*content", content)
print("cls", cls)
print("attrs", attrs)
print("attrs_str", attr_str)
print("resp", resp)
print('-'*10)
return resp
如果你运行这个
tag('div', 'testing', cls='test', **dict(id=33, alt='this is a test'))
tag(**dict(name='div', content=('testing','and testing'), cls='test', id=33, alt='this is a test'))
你得到
name div
*content ('testing',)
cls test
attrs {'id': 33, 'alt': 'this is a test', 'class': 'test'}
attrs_str alt="this is a test" class="test" id="33"
resp <div alt="this is a test" class="test" id="33">testing</div>
----------
name div
*content ()
cls test
attrs {'content': ('testing', 'and testing'), 'id': 33, 'alt': 'this is a test', 'class': 'test'}
attrs_str alt="this is a test" class="test" content="('testing', 'and testing')" id="33"
resp <div alt="this is a test" class="test" content="('testing', 'and testing')" id="33" />
----------
所以你不应该在第二种情况下得到'<div alt="this is a test" class="test" id="33" />'
。 对于完全相同的 function,我得到<div alt="this is a test" class="test" content="('testing', 'and testing')" id="33" />
。
编辑2:可能您的名称空间已损坏,因为名称**kwargs
经常以您在此处使用**attrs
的方式在其他地方使用,因此更改此模块名称/直接导入 function 应该可以解决您的问题。
首先让我们确保我们使用相同的术语:
name, *content, cls=None, **attrs
),'div', 'testing', cls='test', **dict(id=33, alt='this is a test')
)。然后将 arguments 绑定到参数,因此可以在 function 主体中访问它们。
首先让我们看一下 function 签名:
def tag(name, *content, cls=None, **attrs):
...
这个function定义了四个参数:
name
- 位置或关键字参数,content
- 一个可变参数参数,它捕获任意数量的附加位置arguments,cls
- 具有默认值的仅限关键字的参数,attrs
- 一个关键字参数,它捕获任意数量的附加关键字arguments。当您以下列方式调用此 function 时,会发生以下情况:
tag('div', 'testing', cls='test', **dict(id=33, alt='this is a test'))
'div'
绑定到name
,'testing'
被content
捕获,产生一个 1 元组,'test'
绑定到cls
,id=33, alt='this is a test'
由attrs
捕获。 现在关于*content
和**attrs
参数的特殊之处在于它们捕获任意数量的多余 arguments 但它们不能直接绑定。 即你不能绑定content=(1, 2)
。 相反,如果你传递tag('foo', 1, 2)
这个绑定会自动发生。 因此,如果您通过以下方式调用 function:
tag(**dict(name='div', content=('testing', 'and testing'), cls='test', id=33, alt='this is a test'))
然后所有 arguments 都由关键字提供,因此除name
和cls
之外的所有内容都由attrs
捕获。 这是因为*content
仅捕获位置arguments。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.