简体   繁体   English

从关键字参数生成参数字典

[英]Generating a dictionary of parameters from keyword arguments

I'm trying to generate a dict containing the names and the value of the non- None parameters current call.我正在尝试生成一个字典,其中包含当前调用的非None参数的名称和值。 This very much feels like something that should be a built-in, but can't find anything that quite does it in the Python documentation.这很像是应该是内置的东西,但在 Python 文档中找不到任何能做到这一点的东西。

For example, when例如,当

def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):

   # code to generate dict of non-`None` named arguments (see below)

   ...  # other things happen later

is called with the parameters foo(limit=5, lower_bound=100) , I need the following dict: {limit=5, lower_bound=100} .使用参数foo(limit=5, lower_bound=100)调用,我需要以下字典: {limit=5, lower_bound=100}

Is there something that conveniently does that for me?有什么可以方便地为我做的吗?


Potential Solutions潜在的解决方案

So far, I have looked into the following, all of which seem flawed:到目前为止,我已经研究了以下内容,所有这些似乎都有缺陷:

  1. Manually making lists (which has a downside of having more places to things to make changes if, for example, an argument has its name changed)手动制作列表(例如,如果一个参数的名称发生了变化,它的缺点是有更多的地方可以进行更改)
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
    keys = ('limit', 'offset', 'lower_bound', 'upper_bound')
    values = (limit, offset, lower_bound, upper_bound)
    magic_dict = {k: v for k, v in zip(keys, values) if v is not None}
  1. locals()link — which would need everything removed that shouldn't make it into the dictionary (ie the keys with the value of None ). locals()链接— 这将需要删除不应该进入字典的所有内容(即值为None的键)。 This also seems potentially error prone if variables definitions get added above the magic dictionary code , which would also need to be removed.如果在魔法字典代码上方添加变量定义,这似乎也容易出错,这也需要删除。
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
    magic_dict = {k: v for k, v in locals().items() if v is not None}
  1. inspect 's — linksignature and bind , which still requires would a list of the parameters inspect - 链接- signaturebind ,这仍然需要参数列表
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
    sig = signature(foo)
    sig_args = sig.bind(limit, offset, lower_bound, upper_bound).arguments
    magic_dict = {k: v for k, v in sig_args.items() if v is not None}

Other thoughts included making a class to make getattr available其他想法包括创建一个类以使getattr可用

It feels like I'm missing something obvious — feedback would be appreciated!感觉就像我遗漏了一些明显的东西——我们将不胜感激!


Someone suggested What is an elegant way to select all non-None elements from parameters and place them in a python dictionary?有人建议从参数中选择所有非None元素并将它们放入python字典中的优雅方法是什么? , whose responses are primarily "move to **kwargs ". ,其响应主要是“移至**kwargs ”。 My initial reaction is that I would prefer to keep a specific list of arguments — is that bad logic by me?我最初的反应是,我更愿意保留一份具体的论据清单——我的逻辑是不是很糟糕? What is typical best practice with Python? Python 的典型最佳实践是什么?

You can try using decorators:您可以尝试使用装饰器:

def capture(func):
    capture.kwds = None
    def wrap(*args, **kwargs):
        capture.kwds = kwargs
        return func(*args, **kwargs)
    return wrap
    
@capture
def foo(limit=None, offset=None, lower_bound=None, upper_bound=None):
    return None

Now you can call:现在您可以致电:

>>> foo(limit=1, offset=2, lower_bound=3, upper_bound=4)
None
>>> capture.kwds
{'limit': 1, 'offset': 2, 'lower_bound': 3, 'upper_bound': 4}

You can also use the locals method, but copy the locals at the top of your function.你也可以使用 locals 方法,但是在你的函数顶部复制 locals。 At the end one can use the keys of the original locals and select only those in the return statement:最后,可以使用原始本地人的键并仅选择返回语句中的键:

def foo(a=None, b=None, c=None):
    original_locals = locals().copy()
    d = 'test' #Test adding new variable which should not be returned
    return {k:v for k,v in locals().items() if k in original_locals.keys() and v is not None}

foo(1)
>> {'a': 1}
foo(1, 2, 3)
>> {'a': 11, 'b': 2, 'c': 3}

Note that you have to copy the locals, otherwise this method will not work.请注意,您必须复制本地人,否则此方法将不起作用

If you also want to add kwargs :如果您还想添加kwargs

def func(a=None, b=None, c=None, **kwargs):
    org_loc = locals().copy()
    def check_kwargs(d):
        if 'kwargs' in d.keys():
            d.update(d['kwargs'])
            del d['kwargs']
    check_kwargs(org_loc)
    d = 'test'
    new_loc = locals()
    check_kwargs(new_loc)
    return {k:v for k,v in new_loc.items() if k in org_loc.keys() and v is not None}

Then:然后:

func(1)
>> {'a':1}
func(1, test='test')
>> {'a': 1, 'test': 'test'}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM