在Python中只需要一组关键字参数的最佳方法是什么?

时间:2016-01-13 17:42:10

标签: python

我正在编写REST API的包装器,我希望允许用户通过其名称或数据库ID检索小部件。

所以我做了两个关键字参数。现在,似乎你应该只能传递其中一个。实现起来并不算太糟糕,但我不确定它是否更具可读性。

Either

我很好奇:如果我有var times = [ {"ts":"Thu, 20 Aug 2015 18:00:00 GMT"}, {"ts":"Thu, 20 Aug 2015 17:00:00 GMT"}, {"ts":"Thu, 20 Aug 2015 16:00:00 GMT"}, {"ts":"Thu, 20 Aug 2015 15:00:00 GMT"}, {"ts":"Wed, 19 Aug 2015 16:00:00 GMT"}, {"ts":"Wed, 19 Aug 2015 15:00:00 GMT"} ]; var uniqueTimes = {}; times.forEach(function(time) { var t = (time.ts.match(/^(.*?)\s\d+\:/) || [])[1]; t in uniqueTimes ? uniqueTimes[t]++ : uniqueTimes[t] = 1; }); document.body.innerHTML = '<pre>' + JSON.stringify(uniqueTimes, null, 4) + '</pre>';这些关键字参数,该怎么办?我可以接受def get_widget(id=None, name=None): if (id and name) or not (id or name): raise ValueError("Exactly one of (id, name) is required.") # do stuff 并强制执行n,但是我需要迭代kwargs以获取密钥,然后打开密钥。

是否有更好或更易读的方式?

2 个答案:

答案 0 :(得分:1)

“常见”情况是编写多个函数(get_widget_by_idget_widget_by_name等),然后将它们重定向到内部_get_widget函数,以便可以正确共享代码

您也可以使用类创建一个union类型的对象,但这可能会更有效,并且可能对调用者来说看起来很奇怪:

class WidgetKey(object):
  def __init__ (self):
    self._id = None
    self._name = None

  @property
  def id (self):
    return self._id

  @id.setter
  def id (self, val):
    self._id = val
    self._name = None

  @property
  def name (self):
    return self._name

  @name.setter
  def name (self, val):
    self._name = val
    self._id = None

E.g。当有人设置任何值时,只需重置所有其他值。这有点迟钝(并且可以写得更清晰),但是如果你有一大堆参数,这有时很有用。

答案 1 :(得分:1)

老实说,我只是采取这种方法:

def get_widget_by_id(id): pass  # your code here


def get_widget_by_name(name): pass  # your code here

但是,一般情况下,我不知道如何在不滚动自己的检查和异常的情况下允许两个参数之一。我认为最简洁的方法就是这样:

def get_widget(*, arg_one=None, arg_two=None):  # use the * to force keyword args

    if arg_one is None and arg_two is None:
        raise ValueError("No args provided."
                         " Must provide either 'arg_one' or 'arg_two'")
    elif arg_one is not None and arg_two is not None:
        raise ValueError("Too many args provided."
                         " Must provide only 'arg_one' or 'arg_two'")
    else:
        # do your thing

如果您有大量参数,可以使用any / all

if all(_ is None for _ in (arg_one, arg_two)):
    pass
elif all(_ is not None for _ in (arg_one, arg_two)):
    pass

作为另一种选择,您可以始终只允许idname,尽管它可能是多余的,并且只有在匹配两者时才返回小部件。< / p>