TransWikia.com

Dynamically add keywords and their values to a python function from supplied strings

Stack Overflow Asked by Amartya Gaur on January 17, 2021

I want to create a method, which can dynamically add keyword arguments to another function that I intend to call within this method, something like:

def func(query1: str, query2: str):
    func2(query1, query2)

where, the query1, query2 in the func are strings of the type "a=3", "b=4", the func should essentially take these strings and then call them in a keyword argument way like:

func2(a=3, b=4)

The a, b here are not fixed, they may vary, I mean to say I want to be able to take the a and b from the LHS of the string "a=3"

So my function takes the string "a=3" and parses the "a" as the keyword for the other function and the 3 as the value and calls the other function like func2(a=3)

I want to know if this kind of implementation is even possible or if there are any workarounds for achieving the same goal.

The reason why I want this is because I have a django application in which I want to create a model where I can store some filter rules and apply them each time that view is called, so I want to allow the user to select a bunch of filters and then I want to store them in the database and call those rules to get a queryset specific to that user’s preferences.

def some_view(request):
    # Get the filter rule strings from the model
    queryset = some_model.objects.filter(<Pass all the rules here from those strings>)
    return Response

edit: Add more details on the use case

One Answer

Not sure I really understand what you want. You could translate those query strings to a dict, then use that to call the other function with **kwargs:

def f(a, b):
    print(a, b)

def g(*queries):
    return f(**dict((q.split("=", 1) for q in queries)))

>>> g("a=4", "b='string with = in the middle'")
4 'string with = in the middle'

Note: just split("=") might fail if the parameter is a string containing =; thus you might want to use split("=", 1) instead.

However, this passes all the arguments as raw strings; you might want to eval, or rather ast.literal_eval to the values, but that may also pose some risks. Something like this:

import ast
def g(*queries):
    return f(**{k: ast.literal_eval(v)
                for k, v in (q.split("=", 1) for q in queries)})

Correct answer by tobias_k on January 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP