Pass only existing parameters into method - python

I have a code which pass variable into a method if this variable exists in property file.
if all(hasattr(globals().get('properties'), var) for var in ['NAME','VALUE']):
return reader.get_smth(name=properties.NAME, value=properties.VALUE)
else:
return reader.get_smth()
it's obvious that method get_smth() has default values for every passed parameter.
So how can i pass only existing parameters (reader.get_smth(name=properties.NAME) or reader.get_smth(value=properties.VALUE)) avoiding large number of elif's
P.S. Parameters which have to be passed more that 2.

You can use named keywords **kwargs here. First we construct a dictionary that maps the names of the parameters of the get_smth function (e.g. name) to the names of the properties (e.g. NAME):
prop_dict = {'name': 'NAME', 'value': 'VALUE'}
next we can use the following approach:
reader.get_smth(**{k: getattr(properties, v)
for k,v in prop_dict.items()
if hasattr(properties, v)})

Look into star expressions.
Try the following:
reader.get_smth(**properties)
This will unpack key-value pairs from a dictionary into arguments for the function.
The property names will have to be the same as the argument names though (it seems the properties are uppercase and args lowercase in your program).

Related

Django filters with a string variable field

I want to filter a model with a field but I want to pass the field as a string variable. How can I do it?
For example:
the_field = 'name'
TheModel.objects.filter(the_field='Gazelle')
What should I replace the_field with?
You can use dictionary unpacking:
the_field = 'name'
TheModel.objects.filter(**{the_field: 'Gazelle'})
Notice the two asterisks (**) in front of the dictionary. If you call a function with f(**{'a': 4}), that is equivalent to calling it with f(a=4).
or you can make use of a Q object, and pass it a 2-tuple that represents the key and value:
from django.db.models import Q
the_field = 'name'
TheModel.objects.filter(Q((the_field, 'Gazelle')))

Fastest way to add many parameters with their names as keys to a dict programmatically

During many projects, I find myself very frequently assigning variables to a dict, where the name of the variable is the key and the variable's value is the value in the dict. For instance:
def create_results_dict(age, sex, ...):
res = {}
res['age'] = age
res['sex'] = sex
...
return res
I'm wondering what would be a pythonic and efficient (in terms of execution speed) way to doing these assignments dynamically/programmatically? I.e., so that one does not have to write all the assignments manually (lines 3-5, in my example).
Edit: The parameters are just one or more positional or named parameters, i.e., a variable that has a name and a value. I guess, fundamentally the question is, can I receive programmatically the name of a parameter/variable (from a list of parameters passed to a function)?
Simple Method using locals:
def create_results(age, sex, marital_status = "single"):
return {k:v for k, v in locals().items() if not k.startswith('__')}
res = create_results(34, "male")
print(res)
Output:
{'marital_status': 'single', 'sex': 'male', 'age': 34}
def create_results_dic(age, sex, time, name, country):
args = create_results_dic.__code__.co_argcount
items = create_results_dic.__code__.co_varnames
res = {}
for x in items[:args]:
res[x] = eval(x)
return res
If you don't mind using the horribly insecure eval(), this is one solution. It iterates through the first args variables in the scope, where args is the number of args passed to the function. It uses each arg as the name of a key, and gets the value of that variable using eval.
This does of course assume all your args passed are to be added to the dict.

python call function in get method of dictionary instead default value

Need some help in order to understand some things in Python and get dictionary method.
Let's suppose that we have some list of dictionaries and we need to make some data transformation (e.g. get all names from all dictionaries by key 'name'). Also I what to call some specific function func(data) if key 'name' was not found in specific dict.
def func(data):
# do smth with data that doesn't contain 'name' key in dict
return some_data
def retrieve_data(value):
return ', '.join([v.get('name', func(v)) for v in value])
This approach works rather well, but as far a I can see function func (from retrieve_data) call each time, even key 'name' is present in dictionary.
If you want to avoid calling func if the dictionary contains the value, you can use this:
def retrieve_data(value):
return ', '.join([v['name'] if 'name' in v else func(v) for v in value])
The reason func is called each time in your example is because it gets evaluated before get even gets called.

Passing a string as a keyed argument to a function

I am trying to pass an argument to a method with a key to get a Django queryset. The key will be dependent on whatever the user passes through.
Here's an example:
The initial value for filter will be id=1 (a string), I am including a split based on commas in case the user passes in additional filters, such as, title=blahblahblah
filter_split = filters.split(",")
itemFilter = Items.objects # from Django
for f in filter_split:
itemFilter = itemFilter.filter(f)
I have also tried splitting the leftover string as two separate values (key and value) and passing them as such:
itemFilter = itemFilter.filter(key = value)
With no luck.
How can I pass programmatic arguments to a method in Python? Or is there another way to programmatically filter the queryset with Django?
You can pass programmatic arguments with *list and **dict in the argument list.
a = [2,3,4]
function(1, *a) # equal to function(1,2,3,4)
b = {'x':42, 'y':None}
function(1, **b) # equal to function(1, x=42, y=None)
In your case just create a dictionary, assign the key-value pairs from your user input and call itemFilter.filter(**your_dict).
It's not possible to pass a string e.g. "id=1" to filter.
You can create a dictionary dynamically, then pass it to filter using ** unpacking.
key = "id"
value = 1
kwargs = {key: value}
MyModel.objects.filter(**kwargs)
Your other approach to try MyModel.objects.filter(key=value) doesn't work, because it doesn't use the variable key, it tries to filter on the field 'key'

How to save 'arrays' to variable from QueryDict

I have a following structure of QueryDict:
QueryDict: {u'tab[1][val1]': [u'val1'], u'tab[1][val2]': [u'val2'], u'tab[0][val1]': [u'val1'], u'tab[1][val2]': [u'val2']}
I want to store it in an iterable variable so I can do something like this:
for x in xs:
do_something(x.get('val1'))
where x is tab[0] etc
I tried:
dict(request.POST._iteritems())
but it doesn't return tab[0] but tab[0][val1] as an element.
Is it possible to store entire tab[idx] in variable?
Django's QueryDict has a few additional methods to deal with multiple values per key compared to the traditional dict; useful for your purposes are:
QueryDict.iterlists() Like QueryDict.iteritems() except it includes
all values, as a list, for each member of the dictionary.
QueryDict.getlist(key, default)
Returns the data with the requested key, as a Python list. Returns an empty list if the key doesn’t exist and no default value was provided. It’s guaranteed to return a list of some sort unless the default value was no list.
QueryDict.lists()
Like items(), except it includes all values, as a list, for each member of the dictionary.
So you can do something like:
qd = QueryDict(...)
for values in qd.lists():
for value in values:
do_something(value)
Also note that the "normal" dict methods like get always return only a single value (the last value for that key).

Categories