簡體   English   中英

python 使用 *args 和 **kwargs 以及其他僅位置和關鍵字參數解包 arg 列表

[英]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])。

我在這里想念什么?

編輯: Windows 10 中的 Python 3.8.3 x86 在此處輸入圖像描述

*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 應該可以解決您的問題。

首先讓我們確保我們使用相同的術語:

  • A function 聲明參數(在您的示例中name, *content, cls=None, **attrs ),
  • 一個 function 調用接收arguments (例如'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 都由關鍵字提供,因此除namecls之外的所有內容都由attrs捕獲。 這是因為*content僅捕獲位置arguments。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM