使用kwargs传递任意数量的agruments

问题描述 投票:0回答:1

do_something(...)方法期望接收任意数量的参数。每个参数都应以一种或另一种方式包含有关以下信息:

  • [name(类型:str;包含与Python语法不兼容的符号,例如@#.等)]
  • [data(类型:bytes

为了防止意外行为do_something(...) asserts每个参数的namedata的类型:

...
assert isinstance(name, str), ...
assert isinstance(data, bytes), ...
...

每个论点应该(并且应该)仅带来这两条信息。


什么被认为是更好的做法?

将参数作为namedtuple实例(*args)的列表传递

from collections import namedtuple
SomeRepresentation = namedtuple('SomeRepresentation', ['name', 'data'])

foo_bar = [SomeRepresentation('name_of_item_@1', b'...'), SomeRepresentation('name_of_item_@2', b'...'), ...]

do_something(*foo_bar)

假设do_something(*args)将被相应实现:

def do_something(*args):
    for item in args:
        assert isinstance(item, SomeRepresentation), ...
        ...

将参数作为字典传递[**kwargs

foo_bar = {
    'name_of_item_@1': b'...',
    'name_of_item_@2': b'...',
    ...
}

do_something(**foo_bar)

假设do_something(*args)将被相应实现:

def do_something(**kwargs):
    for name, data in kwargs.items():
        ...
python args kwargs
1个回答
0
投票

不使用可变参数,而是使用一对可迭代的对。

from typing import Iterable

def do_something(pairs: Iterable):  # take an iterable...
    for name, data in pairs:          # ...of multiple pairs
        assert isinstance(name, str) and isinstance(data, bytes)
        ...

除非延迟创建对元素,否则可能需要更具体的注释pairs: Iterable[Tuple[str, bytes]]

这既与dict项目和list兼容,也与许多其他类型兼容。

foo_bar_list = [
    SomeRepresentation('name_of_item_@1', b'...'),
    SomeRepresentation('name_of_item_@2', b'...'),
]
do_something(foo_bar_list)

foo_bar_dict = {
'name_of_item_@1': b'...',
'name_of_item_@2': b'...',
}
foo_bar_dict(foo_bar_dict.items())

foo_bar_gen = (
    (f'name_of_item_@{n}', b'...')
    for n in range(1, 1000)
)
do_something(foo_bar_gen)

在这种情况下,使用可变参数是无效的并且具有误导性。

如果呼叫站点和接收方使用* / **,则意味着无需重复包装可迭代对象,然后重新包装。由于也构造了完整的tuple / dict,因此这也防止了使用懒惰的可迭代项/映射。

使用可变参数表示该函数旨在与各个参数一起使用。这里不是这种情况:

# not intended: manual construction of arguments
do_something(SomeRepresentation('name_of_item_@1', b'...'), SomeRepresentation('name_of_item_@2', b'...'))
# not valid: manual passing of keywords
do_something(name_of_item_@1=b'...', name_of_item_@2=b'...')
© www.soinside.com 2019 - 2024. All rights reserved.