您如何以编程方式传递关键字以在python中起作用?

时间:2018-09-04 11:55:59

标签: python refactoring keyword

我要重构一些代码,在python 3中看起来像这样:

  # some_obj.query(streetaddress="burdon")
  # some_obj.query(area="bungo")
  # some_obj.query(region="bingo")
  # some_obj.query(some_other_key="bango")

我怎样才能干燥它,所以我有这样的东西?

# define a list of tuples like so:
set_o_tuples = [
  ("streetaddress", "burdon")
  ("area", "bungo"),
  ("region", "bingo"),
  ("some_other_key", "bango"),
])

然后在函数中调用

for key, val in set_o_tuples:      
  some_obj.query(key=val)

当我尝试运行此代码时,出现如下异常-因为Python不喜欢这样传递关键字:

SyntaxError: keyword can't be an expression

干什么是 的惯用方式,所以我不必像上面的示例那样重复加载代码?

更新:抱歉,我想我上面举的例子错过了一些重要的细节。我基本上有一些像这样的pytest代码

def test_can_search_by_location(self, db, docs_from_csv):
    """
    We want to be able to query the contents of all the below fields when we query by location:
    [ streetaddress, locality, region, postcode]
    """

    search = SomeDocument.search()

    locality_query = search.query('match', locality="some val")
    locality_res = locality_query.execute()

    region_query = search.query('match', region="region val")
    region_query_res = region_query.execute()

    postcode_query = search.query('match', postcode="postcode_val")
    postcode_query_res = postcode_query.execute()

    streetaddress_query = search.query('match', concat_field="burdon")
    field_query_res = field_query.execute()

    location_query = search.query('match', location=concat_value)
    location_query_res = location_query.execute()

    assert len(locality_query_res) == len(location_query_res)
    assert len(region_query_res) == len(location_query_res)
    assert len(streetaddress_query_res) == len(location_query_res)
    assert len(postcode_query_res) == len(location_query_res)

由于有类似的例子,我试图将其中的一些内容弄干,但是在阅读评论后,我重新考虑了一下-空间上的节省并不能证明更改的合理性。感谢您的指点。

2 个答案:

答案 0 :(得分:0)

您可以改为定义字典列表,然后在循环中调用方法时解压缩字典:

list_of_dicts = [
    {"streetaddress": "burdon"}
    {"area": "bungo"},
    {"region": "bingo"},
    {"some_other_key": "bango"},
]

for kwargs in list_of_dicts:      
    some_obj.query(**kwargs)

答案 1 :(得分:-1)

使用dictionary unpacking

some_obj.query(**{key: val})

我不建议您在做什么。原始方法是干净且明显的。您的新产品可能会令人困惑。我会保持原样。这似乎是设计不良的python API,some_obj.query应该在一个函数中仅包含多个关键字参数。您可以这样制作自己的照片:

def query(obj, **kwargs):
    # python 3.6 or later to preserve kwargs order
    for key, value in kwargs.items():
        obj.query(**{key: value})

然后像这样打电话

 query(some_obj, streetaddress='burdon', area='bungo', region='bingo', some_other_key='bango')