This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 2 years ago.
I have used the following code:
from time import time
import datetime
now = datetime.datetime.now()
Report = now.strftime("%Y%m%d_%H%M%S") + "Prueba llamada de funciones" + ".txt"
modo=0
def llamar_funciones():
if (modo==1):
Alimentaciones_1(Report)
Alimentaciones_2(Report)
else:
print("¿Que ensayos de alimentaciones quieres hacer?")
Ensayo=input()
Nombre_Ensayo= "Alimentaciones_" + Ensayo
print(Nombre_Ensayo)
Nombre_Ensayo(Report)
def Alimentaciones_1(Report):
f = open(Report,"a")
f.write("1.funtzioa")
f.close()
def Alimentaciones_2(Report):
f = open(Report,"a")
f.write("\n2.funtzioa")
f.close()
llamar_funciones()
I get the following error:
TypeError: 'str' object is not callable
How can I call the function 1 or 2 depending on the value of the variable "modo"??
You simply need another if statement. You can't call strings, but you can branch based on them.
if Ensayo == "1":
Alimentaciones_1(Report)
elif Ensayo == "2":
Alimentaciones_2(Report)
else:
# ... Handle invalid user input here ...
For what it's worth, you can call a function whose name is a string, but it's poor coding style and extremely bug-prone. To be clear, the following is for educational purposes; do not do it. The above snippet is the accepted way to do this sort of thing.
eval("Alimentaciones_{}".format(Ensayo))(Report) # <-- Bad idea
Python has two functions that might help you, exec() and eval().
They both take a string and treat it like python code (you could use the string from the input and run it), and behave slightly differently.
However, and this is important, don't use them. At all. Those functions are extremely dangerous, as they let the user call every function from your code if they wish, and it's bad practice.
I recommend to use if cases to check for the values you want like:
if my_str == "my_func":
my_func(...)
elif my_str == "my_other_func":
my_other_func(...)
...
This might be tedious but it will let your users call whatever they need to and not more.
Related
This question already has answers here:
How to get class object from class name string in the same module?
(3 answers)
Closed last year.
I am creating a python CLI, where user can provide an operation they want to perform, for eg:
sum 10 15
In my code, I have defined my classes as follows:
class Operation:
# common stuff
pass
class Sum(Operation):
identifier = "sum"
def perform(a, b):
return a + b
class Difference(Operation):
identifier = "diff"
def perform(a, b):
return a - b
Now, in my CLI, if I type sum 10 15 I want to return the result of Sum.perform(10, 15) and similarly if I type diff 10 15, I return the result of Difference.perform(10, 15), as sum is the identifier of class Sum and diff is the identifier of class Difference.
How do I dynamically access the class and its perform method, when I get the input directly from user input?
Classes in Python are first-class citizens, meaning they can be used as standard objects. In particular we can simply store them in a dictionary:
my_dict = {
'sum': Sum,
'diff': Difference,
}
and so on. Then when you get the operation name as string from command line you simply do
my_dict[op_name].perform(a, b)
Note that this is a very basic (and you will soon see problematic, e.g. not all operators accept two arguments) approach to what is known as parsing and abstract syntax trees. This is a huge topic, a bit hard but also very interesting. I encourage you to read about it.
// EDIT: If you want to keep identifier on the class, then you can apply a simple class decorator:
my_dict = {}
def autoregister(cls):
# It would be good idea to check whether we
# overwrite an entry here, to avoid errors.
my_dict[cls.identifier] = cls
return cls
#autoregister
class Sum(Operation):
identifier = "sum"
def perform(a, b):
return a + b
print(my_dict)
You have to remember though to import all classes before you use my_dict. In my opinion an explicit dict is easier to maintain.
Reading your comment, I think you need to interpret the input. The way I would go about this is splitting the input by spaces (based on your example), and then checking that list. For example:
# This is the place you called the input:
input_unsplit = input("Enter your command and args")
input_list = input_unsplit.split(" ")
# Check the first word to see what function we're calling
if("sum") in input_list[0].lower():
result = Sum.perform(input_list[1], input_list[2])
print(result)
# this logic can be applied to other functions as well.
This is a simple solution that could be hard to scale.
=== EDITED ===
I have more to add.
If used correctly, dir() can make a list of defined classes up to a certain point in the code. I wrote a calculator for my precal class, and in it I chose to use dir after defining all the math classes, and then if the name met certain conditions (i.e not main), it would be appended to a list of valid args to pass. You can modify your classes to include some kind of operator name property:
def class Addition:
self.op_name = "sum"
and then perform to take in an array:
def perform(numbers):
return numbers[0] + numbers [1]
To solve many of your scalability issues. Then, after declaring your classes, use dir() in a for loop to append to that valid array, like so:
valid_names = []
defined_names = dir()
for name in defined_names:
if '_' not in name:
if name not in ("sys","argparse","<any other imported module/defined var>"):
valid_names.append(name)
Note that making this step work for you is all in the placement in the script. it's a bit tedious, but works flawlessly if handled correctly (in my experience).
Then, you can use eval (safe in this context) to call the method you want:
# get input here
for name in defined_names:
if eval(name).op_name == input_list[0].lower():
eval(name).perform(input_list)
This should be a fairly easy-to-scale solution. Just watch that you keep the dir check up to date, and everything else just... works.
This question already has an answer here:
Python how to get the calling function (not just its name)?
(1 answer)
Closed 4 years ago.
I want to know how to access a function from within it without naming it directly.
def fact(n):
this = # some code, where we don't use the name "fact"
print(fact == this) # True
if n < 1:
return 1
return n * this(n-1)
The code above should behave exactly like:
def fact(n):
if n < 1:
return 1
return n * fact(n-1)
Does anyone have any ideas?
EDIT:
My question is different from Determine function name from within that function (without using traceback). I need fact == this in the code above to return True.
EDIT2:
#ksbg's answer is a good one, but consider the folowing code:
from inspect import stack, currentframe
def a():
def a():
f_name = stack()[0][3] # Look up the function name as a string
this = currentframe().f_back.f_globals[f_name]
print(a == this)
a()
a() # False
In this case it wont work as expected.
This can be done by inspecting the stack trace. First we look up the function name as a string, and then we go back one frame (or level), and get the function from the module's globals:
from inspect import stack, currentframe
f_name = stack()[0][3] # Look up the function name as a string
this = currentframe().f_back.f_globals[f_name] # Go back one level (to enter module level) and load the function from the globals
However, I don't consider this good practice, and if possible, I would avoid doing that. As already pointed out in comments to your question, doing this without inspecting the stack trace isn't possible in Python.
This question already has answers here:
How do I check if a variable exists?
(14 answers)
Closed 6 years ago.
Is there something like function_exists in PHP for Python3? I am implementing something that allows users (through some web UI) to define simple rules in JSON as follows (in some weird lisp-like structure):
["_and", ["_tautology"], ["tautology"]]
and would like to turn that into a python statement, for instance these functions
import operator
from functools import reduce
def _and(*args):
return lambda context: reduce(operator.and, [arg(context) for arg in args], True)
def _tautology(*_):
return lambda *__: True
by turning that original JSON rule into
_and(_tautology(), _tautology())
Just out of curiousity, is ast made for this kind of task? I did this once before but I am looking for something that is scalable. Because what I did before this was practically maintaining a dictionary like follows
mapping = {'_and': _and}
and the list would keep growing, and that results in more code typed to describe what the string value means, instead of implementing them. Or I should have used another rule engine? Because one of the rule would look like
["_and", ["_equals", "fieldA", "some_value"],
["_equals", "fieldB", "some_other_value"]]
Assuming _equals is
def _equals(field_name, value):
return lambda context: context[field_name] == value
so that the rule is expanded to
_and(_equals('fieldA', 'some_value'),
_equals('fieldB', 'some_other_value'))
TL;DR
Main Question: is there something like function_exists for Python3, is ast suitable for this?
Secondary Question: should I use some sort of rule engine instead?
Regarding the duplicate question report No, I am not checking if a variable exists. I want to know if there is a function that has the same name, as a string value. For example, if I have a string '_and' I want to know if there is a function named _and, not trying to figure out whether this identifier _and is actually a function.
As Morton pointed out, you could use globals() and locals() to fetch a variable using a string containing the name.
In [32]: a = 1
In [33]: def b():
c = 2
print(globals()['a'])
print(globals()['b'])
print(locals()['c'])
....:
In [34]: b()
1
<function b at 0x7f425cae3ae8>
2
But! For your task I would recommend using a decorator that registers your functions to a mapping automatically.
_mapping = {}
def register(f):
_mapping[f.__name__] = f
return f
#register
def _and(*args):
return lambda context: reduce(operator.and_,
[arg(context) for arg in args], True)
#register
def _tautology(*_):
return lambda *_: True
and so your function_exists would be just
_mapping[key]
AST is suitable for inspecting syntax trees generated from parsed python source, modifying existing syntax trees and generating new ones and transpiling to python from a different language by generating syntax trees from it (to name a few uses). So in a way yes, you could generate AST from your JSON and compile that. I believe that is actually what Hy does, though not from JSON, but full blown lisp syntax.
This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Is there a way to store a function in a list or dictionary so that when the index (or key) is called it fires off the stored function?
(3 answers)
Closed 5 months ago.
In Python I want to use user input as a function call. In particular, I have the following code I'm testing out:
def forward(forwardValue):
print("in forward, with value " + forwardValue)
return
command = 'forward' # this would come in as user input
value = '255'
command(value)
What I would like to see is a printout that says: in forward, with value 255
What I do see is an error that:
'str' object is not callable
That error message makes sense, and I can see why what I tested doesn't work, but is there any way to do what I want to do? In other words, can user input be used as a function call?
What I do currently instead is use an "if" statement to check if the user input is the 'forward' statement, and if so to call the function 'forward'. But I would like to be more Pythonesque if possible.
I have a list of about 30 different commands the user can use, each of which commands has a defined function to handle it. My series of 30 "if" and "elif" statements seems clumsy.
Quick and dirty solution
Use globals():
globals()[command](value)
Wiser approach
However, if security is a concern, you may want to limit what can be called from user input. For example define a dictionary of callable functions:
functions = {'forward': forward, 'othercommand': othercommand}
or combine with previous solution to avoid repetitions:
functions = {k: globals()[k] for k in ('forward', 'othercommand')}
Then you would call your function with:
functions[command](value)
Alternative approach
You can use a class as namespace for your user-callable functions:
class Functions:
#staticmethod
def forward(arg):
print("in forward, with value " + forwardValue)
#staticmethod
def othercommand():
pass
(if you are on Python 3.x, #staticmethod is optional in this context)
then access the static methods with getattr():
getattr(Functions, command)(value)
Daanii, what seems to be catching you is that the variable named command contains the string 'forward'. This string object is not your function. Using an if statement, as you said you are already doing, is the most straightforward way to go about it.
If you have many functions and/or you don't necessarily want the function name and the user-passed string to match, then I would suggest using a dictionary.
d = {'foward':forward, 'backward':backward, 'flurb':durf}
def forward(forwardValue):
print("in forward, with value " + forwardValue)
return
def backward(backwardValue):
print("in backward, with value " + backwardValue)
return
def durf(value):
print("in durf, with value " + value)
return
try:
command = raw_input('Enter your thing:\n')
value = '255'
d[command](value)
except KeyError:
print 'The user did not enter a valid string'
This question already has answers here:
Calling a function from string inside the same module in Python?
(2 answers)
Python function pointer
(8 answers)
Closed 9 years ago.
Im writing a python script and what I would like to do is capture the input into a variable and then use that to call a function with that name. Here is an example:
def test():
print "You want to do a test!"
option = raw_input("What do you want to do? ") #User types in test
option()
Now this isnt working since python is not seeing option as a variable but rather is trying to call the function "option". What is the bast way to go about doing this?
eval() will work, but as #MattDMo said it can be dangerous.
A much safer way to do this, if your functions are module globals:
globals()[option]()
globals() is a dictionary mapping strings to the module global objects those strings are bound to. So globals()[option] looks up the string bound to option in that dict, and returns the object; e.g., globals["test"] returns the function object for test(). Then adding () at the end calls that function object. Bingo - you're done.
You want to be very careful about running arbitrary code, but if you absolutely need to, you can use the eval() function.
What might be a better way is to give your user a menu of options, then do testing on the contents of option to see which one they picked, then run that function.
You can use python eval.
From the help page, eval evaluates the source in the context of globals and locals. The source may be a string representing a Python expression or a code object as returned by compile().
For example:
def a():
print "Hello"
inp = raw_input()
eval(inp + "()")
On entering a at the stdin, the function a will be executed. Note that this could be dangerous without any safety checks.
This is, I suppose, an actual use for bare input:
option = input("What do you want to do? ") #User types in test
option()
This is semantically equivalent to eval(raw_input()). Note that in python 3, raw_input becomes input so you will explicitly have to eval it.
The usual caveats of this type of operation being incredibly unsafe apply. But I think that's obvious from your requirement of giving the user access to run arbitrary code, so...
I like using a dict in situations like this. You can even specify a default option if the user provides an answer that isn't expected.
def buy_it():
print "use it"
def break_it():
print "fix it"
def default():
print "technologic " * 4
menu = {"buy it": buy_it, "break it": break_it}
option = raw_input("What do you want to do? ")
menu.get(option, default)()