首页 > 解决方案 > 在 Python 中使用 **kwargs 的正确方法

问题描述

我看了一下这个问题,但它并没有完全回答我的问题。例如,我采用了一种简单的方法来打印我的名字。

def call_me_by_name(first_name):
    print("Your name is {}".format(first_name))

后来,我意识到,可选地,我还希望能够打印中间名和姓氏。我做了以下更改以适应使用 **kwargs 的情况,担心将来我可能会为名称本身添加更多字段(例如第 3、第 4、第 5 个名称等)

我决定使用 **kwargs

def call_me_by_name(first_name,**kwargs):

    middle_name = kwargs['middle_name'] if kwargs.get('middle_name') else ""
    last_name = kwargs['last_name'] if kwargs.get('last_name') else ""

    print("Your name is {} {} {}".format(first_name,middle_name,last_name))

我唯一担心的是,随着我继续实现对更多名称的支持,我最终会为每个可能会或可能不会出现的关键字参数编写一行代码。我想找到一个尽可能 Pythonic 的解决方案。有没有更好的方法来实现这一目标?

编辑 1

我想使用关键字参数,因为这只是一个示例程序。实际用例是通过文件解析。到目前为止的关键字参数将支持从

1) 文件中的特定字节。
2) 文件中的特定行号。

在任何给定的时间点只能设置这两个条件中的一个(因为不可能同时从文件中的特定字节偏移和行号中读取。)但是在未来,例如从第一次出现的字符中解析文件等。可能有 10-20 种不同的此类条件,我的方法应该支持但只有一个条件会由调用者随时设置。除非没有其他选择,否则我不希望有 20-30 个不同的 IF 条件。

标签: pythonkeyword-argument

解决方案


你有两个不同的问题,有两种不同的 Pythonic 方式来回答这些问题。

1-您首先担心的是,在格式化字符串时,您开始支持的参数越多,您就不想继续添加新行。解决此问题的方法是使用 a defaultdict,因此当您不提供特定的关键字参数并且str.format_map接受 dict 作为输入关键字参数以进行格式化的一种方式时,您可以返回一个空字符串。这样,您只需要更新您的字符串以及要打印的关键字参数:

from collections import defaultdict
def call_me_by_name(**kwargs):
    default_kwargs = defaultdict(str, kwargs)
    print("Your name is {first_name} {second_name} {third_name}".format_map(default_kwargs))

2-另一方面,如果在回答第二个问题时,您想根据关键字参数提供不同的行为,例如更改字符串的外观或提供不同的文件查找功能,而不使用 if 语句,则必须添加不同的函数/方法并从此通用函数/方法调用它们。这里有两种方法:

哎呀:

class FileLookup:

    def parse(self, **kwargs):
        return getattr(self, next(iter(kwargs)))(**kwargs)

    def line_number(self, line_number):
        print('parsing with a line number: {}'.format(line_number))

    def byte_position(self, byte_position):
        print('parsing with a byte position: {}'.format(byte_position))

fl = FileLookup()
fl.parse(byte_position=10)
fl.parse(line_number=10)

模块:

def line_number(line_number):
    print('parsing with a line number: {}'.format(line_number))

def byte_position(byte_position):
    print('parsing with a byte position: {}'.format(byte_position))

def parse(**kwargs):
    return globals()[next(iter(kwargs))](**kwargs)

parse(byte_position=29)
parse(line_number=29)

推荐阅读