Let's say I have a function that can take various kinds of parameter values, but I don't want to (as a constraint) pass arguments explicitly. Instead, I want to pass them as a string.:
def func(param)
return param+param
a = 'param=4'
func(<do something to a>(a))
>>8
Is this possible in python?
I want to use this idea in Django to create Query filters based on GET parameters in a dictionary and then just chain them using their keys.
lookup_dic = {'user': 'author=user',
'draft': 'Q(publish_date_lte=timezone.now())|
Q(publish_date_isnull=True)'}
Based on whether the user and draft keywords are passed in the GET parameters, this would be read out like:
queryset.objects.filter(author=user).filter(Q(publish_date_lte=timezone.now())|
Q(publish_date_isnull=True))
I understand that I can do this by replacing the author=user by Q(author__name=user), but I wanted to know if this string comprehension feature is implemented in python in general?
Use eval
def func(param=0):
return param+param
a = 'param=4'
eval('func(' + a +')')
Are you looking for this?
def func(param):
return param + param
a = 'param=4'
parameter, value = a.split("=")
print(func(**{parameter: int(value)}))
# >> 8
Related
I am writing a function that takes a lot of keywords.
I have a dictionary which is very lengthy that contains many of these keywords that already exists in my code and is being used elsewhere. E.g.
{'setting1':None, 'setting2': None....}
I am wondering is there a way, when I define my function, for me to set all of these as keywords, rather than having to type them out again like this:
def my_function(setting1=None, setting2=None, **kwargs)
To be clear, essentially I want to set all of the contents of the dictionary to be keywords with default value None, and when I call the function I should be able to change their values. So I am not looking to provide the dictionary as kwargs upon calling the function.
While not exactly the same, I ususally prefer to save the arguments in **kwargs and use .get() to get the value or None:
def my_function(**kwargs):
do_something(kwargs.get("alpha"), kwargs.get("beta"))
.get() on a dictionary returns the value if a key exists, or None of it does not. You can optionally specify a different default value as a second argument if you like.
When creating a function, you will need to implement how your arguments are used. By automatically creating arguments you end up adding arguments and forgetting to implement a behaviour for them.
# Manually defined.
def func(a, b, c, d):
return a + b / c * d
# Auto-defined - Human error.
def func(""" auto define a,b,c,d,e,f,g,h """):
return a + b / c * d # <- you only use half of the arguments. Confusing at best.
# Auto-defined - Inputs unclear, code is not explicit.
def func(defind_my_args):
return a + b / c * d
If you need to reuse "code behaviour" to the point that you can "inherit" parameters, maybe you should be using an object instead.
I am trying to create function that would take a random amount of parameters some defined, others not.
So I have this search function that would sometimes take all of the arguments, but sometimes just url, query and authHeader.
I did study about *arg, **kwards, but AFAIK they did not suit in this case.
Or do I always have to give them some value in my case, for example "null"? But that means I need to assign a value to variable and could not just pass it that time?
def search(url, query, resultLimit, resultInfoSize, authHeader):
searchRequest = session.post(url + '/services/search?q=' + query + '&num=' + resultLimit + '&datalinesToReturn='+ resultInfoSize, headers=authHeader)
searchData = searchRequest.json()
return searchData
Any opinion much appreciated.
Update
as #Jerrybibo kindly stated I got my aswer:
So adding if condition in the function was what I was looking for. Changing the default values inside the function if on call none are provided.
def search(url, query, resultLimit, authHeader, resultLimit=None, resultInfoSize=None):
if resultLimit == None: resultLimit='50'
if resultInfoSize == None: resultInfoSize=''
searchRequest = session.post(url + '/services/search?q=' + query + '&num=' + resultLimit + '&datalinesToReturn='+ resultInfoSize, headers=authHeader)
searchData = searchRequest.json()
return searchData
Looking at your question, I believe one way of working around this is to have several of your function parameters set to default sentinel values (usually None; use whichever default value makes sense in your scenario) so that you do not have to pass the values on function call; and if you do pass them, they get processed just like normal parameters. Your function definition would look like this:
def search(url, query, authHeader, resultLimit=None, resultInfoSize=None):
Additionally, you may have to change your searchRequest definition in the function in the event that resultLimit or resultInfoSize is None.
Question
In python, what is the shortest/easiest way to create a function which allows me to access a variable by concatenating two string literals to generate the variable's name?
Background
In C, I can do something like so:
#define CONCAT(x,y) x ## _ ## y
Then, later in my code, I could do something like:
int i = CONCAT(PRODUCT,BANANA).
Assuming a macro exists with the name PRODUCT_BANANA, its value is now assigned to i. I can accomplish something similar in shell scripts via indirection.
Question - Redux
How can I accomplish this same functionality in python? I'm doing this because I have a python class with thousands of variables for dozens of different products, i.e.
class A(object):
BANANA_ADDRESS0 = 0xABCD;
PINEAPPLE_ADDRESS0 = 0x1234;
BANANA_ADDRESS1 = 0x4567;
PINEAPPLE_ADDRESS1 = 0x1000;
I'd like to be able to have a function that can be, for example, executed via someFunc("BANANA", "ADDRESS0"), resolve the value as A.BANANA_ADDRESS0, and return the associated value (0xABCD, in this case).
Extra
Assuming the above is possible, is it possible to have the function always interpret the supplied function arguments as string literals, so function calls don't need the arguments wrapped in single/double quotes? i.e. so it can be called via someFunc(BANANA, ADDRESS0), rather than someFunc("BANANA", "ADDRESS0")?
The first part is easy:
class A(object):
BANANA_ADDRESS0 = 0xABCD;
PINEAPPLE_ADDRESS0 = 0x1234;
BANANA_ADDRESS1 = 0x4567;
PINEAPPLE_ADDRESS1 = 0x1000;
#classmethod
def some_func(cls, name_a, name_b):
name = '{}_{}'.format(name_a, name_b)
return getattr(cls, name)
value = A.some_func('BANANA', 'ADDRESS1')
But the second part is not possible unless you have a limited set of names, in which case you would also have to have
BANANA = 'BANANA'
PINEAPPLE = 'PINEAPPLE'
etc
If you just want to do this for class/instance attributes, you want getattr. It takes a string argument, which you can construct any way you like:
getattr(A, "BANANA" + "_" + "ADDRESS0")
You could of course write a simple wrapper if you wanted, but in my opinion that would be obfuscatory for no benefit.
Building the string passed to getattr any way you want includes using other constructs like for loops if appropriate. For instance, suppose you have iterables of elements of the attribute names and want to get them all:
for first_part in first_parts:
for second_part in second_parts:
print(getattr(A, first_part + "_" + second_part))
For your "extra" block - well, BANANA means a variable named BANANA, not the literal string. You could define such a string constant if you really wanted, but I wouldn't. There is no good way to tell Python to always assume an unresolved variable name actually means a string literal, and I think it would be a bad idea to do so if you could.
Just use a dict. i.e.
A = {
"BANANA_ADDRESS0": 0xABCD,
"PINEAPPLE_ADDRESS0": 0x1234,
"PINEAPPLE_ADDRESS1": 0x1000
}
And then you can do something like this:
var1 = "BANANA" # or any other value
var2 = "ADDRESS0" # or any other value
myValue = A[var1 + "_" + var2]
I need to pass inequalities to a function for evaluation within the function. Is there a way to evaluation the inequality if passed as a string? Or must I pass a representation of the inequality and use if/else statements to generate the sign?
Your question is a little vague, but it sounds like you want to evaluate a string containing an expression (such as x > 5). Rather than doing that, which is unnecessarily complex, and potentially a security hazard, just define a function, either in the conventional way or using lambda.
def gt5(x):
return x > 5
or
gt5 = lambda x: x > 5
These are both equivalent; now you can pass around gt5 however you like, and when the time comes, you simply call it
y = 6
if gt5(y):
...
As Gerrat's answer suggests, the operator module may also be useful for things like this.
Now that I know you are processing user strings, I would definitely suggest creating a dictionary that maps strings to functions. (Perhaps that's what you meant in your title?) Passing userland strings into getattr seems bad in a number of ways. What happens if you want to add a string that doesn't correspond to an attribute of operator? What happens if the user passes in a string corresponding to a private attribute? Better to create a custom dictionary mapping strings to functions. A dict allows you to specify just those strings you want to accept.
func_dict = {
'lt' : operator.lt,
'gt' : operator.gt,
'nand' : lambda x, y: not (x and y)
}
You could still save yourself work by using getattr + operator to build the dict from a list of strings that you want to accept. Something like:
func_dict = dict((s, getattr(operator, s)) for s in ['lt', 'gt'])
Then update func_dict like so:
custom_dict = {
'nand' : lambda x, y: not (x and y)
}
func_dict.update(custom_dict)
From there you can easily call functions in the dict like so:
>>> func_dict['lt'](5, 7)
True
You could use the operator module, and pass the appropriate method on it:
import operator
def check(op, a, b)
return op(a,b)
op = operator.ne
check(op, 2,3)
>>> True
I'm trying to execute a Django query:
#att.name is a string
kwargs = {att.name : F('node__product__' + att.name) }
temps = Temp.objects.exclude(**kwargs)
I'm wondering if this is correct. All the examples I've seen so far use strings in the values, but what if the value is a function, should I make the value a string, like this?
kwargs = {att.name : 'F('node__product__' + att.name)' }
Does the function in the value get executed eagerly in the argument list or does it wait until it's needed?
In python, expressions are always evaluated eagerly. There is no lazy evaluation in python. Some libraries get around the absence of this useful feature by allowing values that should be of some specific type to instead be a string, which it later evals. You can declare some parts of a django model this way (so that you can declare mutually referential foreign key relationships), but django's query interface does not. You wouldn't normally be able to use this kind of technique when a string is "expected", because you'd have no way to distinguish string values from strings that should be evaled.
Only the first one is correct:
kwargs = {att.name : F('node__product__' + att.name) }
temps = Temp.objects.exclude(**kwargs)
I don't understand how lazy/eager is related to this question.
Function arguments are evaluated before the function is called:
>>> def foo(x): return x
...:
>>> foo(sum(range(10)))
<<< 45
When you create a dict everything is evaluated at that moment:
>>> kwargs = {'key': sum(range(10))}
>>> kwargs
<<< {'key': 45}
So...
>>> def foo(**kwargs): return kwargs
...:
>>> foo(**kwargs)
<<< {'key': 45}
I am not sure if this question is because you are curious or if you are trying to find ways to load querys. So I will take a guess:
I would be using the Q() function and maybe load them on args to later use a for to set them on the Temp.objects.exclude, would be something like this:
def mylolfunc(self, *args,**kwargs):
queryset = Q()
for query in args:
queryset |= query
return Temp.objects.filter(queryset)
Where query is a Q(att.name = F('node_product_' + att.name)) or a lot more of Q objects.
Here is the documentation if you want to check it out.
This query will not execute until you ask for information, so it would be lazy. by that I mean until you do something like
myquery = mylolfunc(*args)
myquery[0] #-----> executes query here