Construct callable function from string [duplicate] - python

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 5 years ago.
How to construct and call a function from a string?
For example, consider three different functions and a list of strings, I want to be able to use the items in list of strings to construct and call the appropriate function
def do_function1():
return 'done function1'
def do_function2():
return 'done function2'
def do_function3():
return 'done function3'
listOfstr = ['function1','function2','function3']
for item in listOfstr:
result = 'do_'+item()
print(result)
result = 'do_'+item()
TypeError: 'str' object is not callable

The problematic code is
listOfstr = ['function1','function2','function3']
for item in listOfstr:
result = 'do_'+item()
In the first loop item, will have the value 'function1'. You are calling this string as if it were a function. But strings are not callable and have no code assigned to them!
Then, you go on with the for loop before doing anything.
Simply refer to item, like this:
for item in listOfstr:
func_name = 'do_' + item
func = globals()[func_name]
func()

The most explicit way would be to have a dictionary of those functions:
funcs = {
'function1': do_function1,
'function2': do_function2,
'function3': do_function3,
}
funcs[item]()
That way you can also name your functions whatever you want, decouple from item names, make them methods, move to other modules etc without breaking the general design. The other way is globals, as already answered.

First of all, usually you won't need this. Instead of putting strings in a list, you can also put functions themselves in a list like this:
def do_function1():
return 'done function1'
def do_function2():
return 'done function2'
def do_function3():
return 'done function3'
list_of_functions = [do_function1, do_function2, do_function3]
for item in list_of_functions:
result = item()
print(result)
However, if you insist, you can do it like this:
locals()["do_function1"]()
locals() gives you a dictionary of locally defined objects by name.

Related

Automatic method extensions? [duplicate]

This question already has answers here:
Local variables in nested functions
(4 answers)
Closed 2 years ago.
I have a Python class MyObject (a subclass of tuple) and another class for a set of these objects, MyObjectSet (a subclass of set). I’d like that, for any non-builtin method that I define for MyObject, a method of the same name be defined for MyObjectSet with value equal to the sum of the method over the contents of the MyObjectSet.
I had thought that something like the code below would work, but the result doesn’t match my intended outcome. In practice MyObject and MyObjectSet have a lot more to them and are justified.
class MyObject(tuple):
def stat_1(self):
return len(self)
def stat_2(self):
return sum(self)
class MyObjectSet(set):
pass
for stat_name in dir(MyObject):
if not stat_name.startswith("__"):
stat_func = getattr(MyObject, stat_name)
if callable(stat_func):
setattr(MyObjectSet, stat_name, lambda S: sum(stat_func(p) for p in S))
if __name__ == "__main__":
S = MyObjectSet(MyObject(t) for t in [(1,2), (3,4)])
result, expected = S.stat_1(), sum(p.stat_1() for p in S)
print(f"S.size() = {result}, expected {expected}")
result, expected = S.stat_2(), sum(p.stat_2() for p in S)
print(f"S.sum() = {result}, expected {expected}")
Is there any way to achieve this functionality?
replace your lambda with this:
lambda S, f=stat_func: sum(f(p) for p in S)
It copies the stat_func into f, instead of capturing a reference to it, which was what happened in your original code (so all stat_funcs inside your different lambdas ended up being the last value assigned to the stat_func in the for loop.
You can simply override __getattr__ to treat any possible method call as a summing wrapper around the object's method of the same name. This simple example will just raise an AttributeError if the underlying method doesn't exist; you may want to catch the exception and raise another error of your own.
class MyObjectSet(set):
def __getattr__(self, mn):
return lambda: sum(methodcaller(mn)(x) for x in self)

why return list_name.append(something) returns none? [duplicate]

This question already has answers here:
Why does [1].append(2) evaluate to None instead of [1,2]? [duplicate]
(2 answers)
Closed 2 years ago.
when I define function f which append a value to a list
in this structure :
list_name=[]
return list_name.append(a)
>>>print(f(1))
none
and when i define it in the following structure:
def f (a) :
list_name=[]
list_name.append(a)
return list_name
it gives the right output
>>>print(f(1))
[1]
>>>print(f(2))
[2]
what is the difference between return list_name.append(a) and
list_name.append(a)
return list_name
??
The return type of the append function is None, which is a Pythonic way of saying that it does not return a value.
Basically, the append function does not return a value, rather performs an operation (adding elements to the of the list), and that's it.
You are trying to return the result of a function which does not return a value, and hence, the output is None.
On the other hand, when you try the second way, the append operation has already taken place, and you return an object of type <List>, which works without any problem.
list_name.append(a) doesn't explicitly return anything, it just changes the list. It's sort of like how print doesn't return anything, it just prints what you gave it onto the screen. This is a common pattern where when a method like append which just modifies an object or has some effect doesn't return anything. But in Python, you can't not return anything, so the default is to just return None. In fact, both list_name.append(a) and print('hello') really do return None, even though the definitions of those methods/functions might not explicitly say return None at the end. For example, try running this code:
def do_something():
a = 1
x = do_something()
print(x)
The value of x is None despite us not writing return None at the end of do_something.

list of functions Python

I have a list of patterns:
patterns_trees = [response.css("#Header").xpath("//a/img/#src"),
response.css("#HEADER").xpath("//a/img/#src"),
response.xpath("//header//a/img/#src"),
response.xpath("//a[#href='"+response.url+'/'+"']/img/#src"),
response.xpath("//a[#href='/']/img/#src")
]
After I traverse it and find the right pattern I have to send the pattern as an argument to a callback function
for pattern_tree in patterns_trees:
...
pattern_response = scrapy.Request(...,..., meta={"pattern_tree": pattern_tree.extract_first()})
By doing this I get the value of the regex not the pattern
THINGS I TRIED:
I tried isolating the patterns in a separate class but still I have the problem that I can not store them as pattern but as values.
I tried to save them as strings and maybe I can make it work but
What is the most efficient way of storing list of functions
UPDATE: Possible solution but too hardcoded and it's too problematic when I want to add more patterns:
def patter_0(response):
response.css("#Header").xpath("//a/img/#src")
def patter_1(response):
response.css("#HEADER").xpath("//a/img/#src")
.....
class patternTrees:
patterns = [patter_0,...,patter_n]
def length_patterns(self):
return len(patterns)
If you're willing to consider reformatting your list of operations, then this is a somewhat neat solution. I've changed the list of operations to a list of tuples. Each tuple contains (a ref to) the appropriate function, and another tuple consisting of arguments.
It's fairly easy to add new operations to the list: just specify what function to use, and the appropriate arguments.
If you want to use the result from one operation as an argument in the next: You will have to return the value from execute() and process it in the for loop.
I've replaced the calls to response with prints() so that you can test it easily.
def response_css_ARG_xpath_ARG(args):
return "response.css(\"%s\").xpath(\"%s\")" % (args[0],args[1])
#return response.css(args[0]).xpath(args[1])
def response_xpath_ARG(arg):
return "return respons.xpath(\"%s\")" % (arg)
#return response.xpath(arg)
def execute(function, args):
response = function(args)
# do whatever with response
return response
response_url = "https://whatever.com"
patterns_trees = [(response_css_ARG_xpath_ARG, ("#Header", "//a/img/#src")),
(response_css_ARG_xpath_ARG, ("#HEADER", "//a/img/#src")),
(response_xpath_ARG, ("//header//a/img/#src")),
(response_xpath_ARG, ("//a[#href='"+response_url+"/"+"']/img/#src")),
(response_xpath_ARG, ("//a[#href='/']/img/#src"))]
for pattern_tree in patterns_trees:
print(execute(pattern_tree[0], pattern_tree[1]))
Note that execute() can be omitted! Depending on if you need to process the result or not. Without the executioner, you may just call the function directly from the loop:
for pattern_tree in patterns_trees:
print(pattern_tree[0](pattern_tree[1]))
Not sure I understand what you're trying to do, but could you make your list a list of lambda functions like so:
patterns_trees = [
lambda response : response.css("#Header").xpath("//a/img/#src"),
...
]
And then, in your loop:
for pattern_tree in patterns_trees:
intermediate_response = scrapy.Request(...) # without meta kwarg
pattern_response = pattern_tree(intermediate_response)
Or does leaving the meta away have an impact on the response object?

python select a function based on the value in a dictionary [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 6 years ago.
I want to select a function based on the value of a dictionary:
dict = {"func_selector":"func1", "param_value":"some_value"}
# defined a function
def func1(param):
# some function code
Now, I want to select the function based on the value of some key, so that it can achieve something like:
# calling a function based on some dict value
dict["func_selector"](dict["param_value"])
The syntax is probably wrong, but I am wondering if it is possible to do that in Python or something similar.
Try storing the value of the function in the dictionary, instead of its name:
def func1(param):
print "func1, param=%r" % (param,)
d = {"func_selector":func1, "param_value": "some value"}
Then you can say:
>>> d['func_selector'](d['param_value'])
func1, param='some value'
The best approach IMO is do it like this
def func1(param):
#code
some_value = ... #The value you need
my_dict = {"func_selector": func1, "param_value": some_value }
And then
my_dict["func_selector"](my_dict["param_value"])
Now, if you only have the name of the function you need to call getattr
And call it
getattr(my_class, my_dict["func_selector"])(my_dict["param_value"])
my_class is the class which contains the method. If it's not in a class I think you can pass self

In Python how do I run an array of functions

Here is my problem I have a number of functions defined and I want to loop through a list of these functions and run them one at a time in the correct order.
def one():
print "One "
def two():
print "Two "
def three(): "Three "
print "Three "
arr = ('one','two','three')
for fnc in arr:
<some how run the function name in the variable fnc>
Any Help Appreciated, as I am a beginner with python and django.
Python functions are first order objects; just put them in the sequence:
arr = (one, two, three)
for fnc in arr:
fnc()
You could store strings too, but then you need to turn those back into the function object first. That'd just be extra busywork you don't really need to do.
You can still turn strings into objects; the globals() function gives you the current global namespace as a dictionary, so globals()['one'] gives you the object referenced by the name one, but this would also give you access to every global in your module; if you then made a mistake it could lead to hard to track bugs or even security holes (as end-users could potentially abuse functions you didn't intent to be called).
If you really need to map names to functions, because, say, you need to take input from something else that only produces strings, use a predefined dictionary:
functions = {
'one': one,
'two': two,
'three': three,
}
and map your string to the function:
function_to_call = 'one'
functions[function_to_call]()
Your function names do not need to match the string values here. By using a dedicated dictionary you limit what can be called.
It depends on where the functions are defined, but if they are in the current context, you can get a reference to them by retrieving them from the globals function:
def fn():
return ":)"
for f in['fn']:
print globals()[f]()
Seems to work...
method_name = 'one'
possibles = globals().copy()
possibles.update(locals())
method = possibles.get(method_name)
if not method:
raise Exception("Method %s not implemented" % method_name)
returned_value = method()
For your specific example, simply use eval:
arr = ('one','two','three')
for fnc in arr:
eval(fnc + '()')
Be aware that using eval() is considered bad practice by some.

Categories

Resources