I want to call that function by extracting the first word from the string. For example my string is like:
"my_func arg_1 arg_2"
# ^ ^ ^ second argument of function
# ^ ^ first argument of function
# ^ name of the function
where my_func is a name of the function already defined.
Based on the above mention string, I want to dynamically execute the my_func function. So, my function call should be like:
my_func(arg_1, arg_2)
Currently I am trying to achieve this via using eval:
eval(command.split(' ', 1)[0])
How can I achieve this?
You may use locals() (or globals()) to fetch the reference of function based on string. Below is the sample example:
# Sample function
def foo(a, b):
print('{} - {}'.format(a, b))
# Your string with functions name and attributes
my_str = "foo x y"
func, *params = my_str.split()
# ^ ^ tuple of params string
# ^ function name string
Now, pass the function string as a key to the locals() dict with *params as argument to the function as:
>>> locals()[func](*params)
x - y # output printed by `foo` function
Regarding the split method, by default the delimiter is space so you don't actually need to define that your delimiter is space and as you want the first item in the list, you just need to type the index 0 [0].
locals returns a dictionary with a current local symbol table. globals returns a dictionary with global symbol table.
var = "my_func arg_1 arg_2"
print (locals()[var.split()[0]]())
Or
var = "my_func arg_1 arg_2"
print (globals()[var.split()[0]]())
If the function was part of an object you could use the getattr built-in function.
var = "my_func arg_1 arg_2"
getattr(object, var.split()[0])
getattr(object, name[, default])
Return the value of the named
attribute of object. name must be a string. If the string is the name
of one of the object’s attributes, the result is the value of that
attribute. For example, getattr(x, 'foobar') is equivalent to
x.foobar. If the named attribute does not exist, default is returned
if provided, otherwise AttributeError is raised.
If you define you functions up front you can have greater control over their name mapping.
def my_func(a):
print(a)
functions = {'my_func': my_func}
def exe(text):
command = text.split(" ")
f = command[0]
args = command[1:]
if f in functions:
functions[f](args)
exe("my_func arg_1 arg_2")
Something along the lines of:
Check if the function exists inside the local scope.
If it does exist then run it using eval().
def add():
print("do something")
def find_function(funct_name, defined_names):
if defined_names.get(funct_name) is None:
print("no function called {}".format(funct_name))
return
eval(funct_name + "()")
# access local user defined names.
defined_names = locals()
#print(defined_names)
function_name = 'add'
find_function(function_name ,defined_names)
Output:
do something
Related
So I was reading this wonderful piece which tries to explain decorators in python.
My question is specific to this code snippet.
def surround_with(surrounding):
"""Return a function that takes a single argument and."""
def surround_with_value(word):
return '{}{}{}'.format(surrounding, word, surrounding)
return surround_with_value
def transform_words(content, targets, transform):
"""Return a string based on *content* but with each occurrence
of words in *targets* replaced with
the result of applying *transform* to it."""
result = ''
for word in content.split():
if word in targets:
result += ' {}'.format(transform(word))
else:
result += ' {}'.format(word)
return result
markdown_string = 'My name is Jeff Knupp and I like Python but I do not own a Python'
markdown_string_italicized = transform_words(markdown_string, ['Python', 'Jeff'],
surround_with('*'))
print(markdown_string_italicized)
What I don't understand is how did the function surround_with() get the variable word (when passed on by transform(word) inside transform_words()) in it's scope? I mean we have only declared a holding variable (as a function argument) for what the surrounding value should be and nothing else. Then how was word available to it?
What am I missing here?
The surround_with() function returns another function object with a closure:
def surround_with(surrounding):
"""Return a function that takes a single argument and."""
def surround_with_value(word):
return '{}{}{}'.format(surrounding, word, surrounding)
return surround_with_value
So surround_with_value is returned; it is this function that prepends and appends the value of surrounding to whatever is passed in:
>>> def surround_with(surrounding):
... """Return a function that takes a single argument and."""
... def surround_with_value(word):
... return '{}{}{}'.format(surrounding, word, surrounding)
... return surround_with_value
...
>>> function = surround_with(' foo ')
>>> function
<function surround_with_value at 0x108ac16e0>
>>> function('bar')
' foo bar foo '
The surround_with_value() function was returned and a reference to it was stored in the name function. That function object references surrounding as a closure:
>>> function.__closure__
(<cell at 0x108a8a590: str object at 0x1074c4060>,)
>>> function.__closure__[0].cell_contents
' foo '
and each time you call it that closure is dereferenced and the contents are used.
So surround_with() produces a function object, and such function (as the result of surround_with('*')), is passed to transform_words() as the 3rd argument:
transform_words(markdown_string, ['Python', 'Jeff'],
surround_with('*'))
so it is assigned to the variable transform:
def transform_words(content, targets, transform):
Thus, each time you call transform, you really are calling the nested surround_with_value() function with '*' as the surrounding closure, and word is being passed in:
result += ' {}'.format(transform(word))
I think I understood it,
When we call surround_with('*'), it returns the function surround_with_value() which is then returning the value '{}{}{}'.format('*', word, '*').
Now the very same function takes an argument (word here) which is then passed inside transform_words() and renamed as transform().
Inside it we finally pass the value for word.
Closure can be very confusing and this example might not be the best to show why surround_with_value() remembers surround with(surrounding) event if it's not in its scope.
I strongly advice you to read this excellent blog showing all concept you need to understand to understand decorators. Step1: Scope-->Step2: Closure-->Step3: Decorators
Take some time and read it from the beginning.
http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/
I need to monkey-patch my library to replace an instance of a symbol, and it's getting referenced by some function closures. I need to copy those functions (since I also need access to original unpatched version of the function as well), but __closure__ is immutable, and I can't copy.copy it, so how can I create new closure cells objects in Python 2.7?
I for example given this function
def f():
def incorrectfunction():
return 0
def g():
return incorrectfunction()
return g
def correctfunction():
return 42
func = f()
patched_func = patchit(f) # replace "incorrectfunction"
print func(), patched_func()
And I want to see
0, 42
The simple way to make a closure cell would be to make a closure:
def make_cell(val=None):
x = val
def closure():
return x
return closure.__closure__[0]
If you want to reassign an existing cell's contents, you'll need to make a C API call:
import ctypes
PyCell_Set = ctypes.pythonapi.PyCell_Set
# ctypes.pythonapi functions need to have argtypes and restype set manually
PyCell_Set.argtypes = (ctypes.py_object, ctypes.py_object)
# restype actually defaults to c_int here, but we might as well be explicit
PyCell_Set.restype = ctypes.c_int
PyCell_Set(cell, new_value)
CPython only, of course.
in lambda:
def make_cell(value):
fn = (lambda x: lambda: x)(value)
return fn.__closure__[0]
got anwer from https://github.com/nedbat/byterun/blob/master/byterun/pyobj.py#L12
If you want an empty cell (which is what I found this question for) (One where referencing it raises a NameError: free variable '...' referenced before assignment in enclosing scope and accessing it's cell.cell_contents raises a ValueError: Cell is empty), you can make a value a local variable, but never let it be assigned:
def make_empty_cell():
if False:
# Any action that makes `value` local to `make_empty_cell`
del value
return (lambda: value).__closure__[0]
You can combine them like this:
_SENTINEL = object()
def make_cell(value=_SENTINEL):
if value is not _SENTINEL:
x = value
return (lambda: x).__closure__[0]
So calling with no arguments returns an empty cell, and with any value, a cell with that value.
If you don't care about empty cells, you can do:
def make_cell(value):
return (lambda: value).__closure__[0]
Note that it is func_closure in older Python 2, instead of __closure__.
I am trying to print a procedure in Python. How do I print it?
Here is my code
def proc(a,b):
if test(a):
return b
return a
print proc(a,b)
But I get this error:
NameError: name 'a' is not defined
Thanks in advance.
a is the name of the local variable used to hold the value of the first argument passed to the function when it is called. When actually calling it, you need an actual value, or a variable defined in the scope where the function is called. For example:
def proc(a,b):
if test(a):
return b
return a
x = 6
print proc(x, 7)
Now when proc is called, the value of the variable x and the value 7 are passed to proc. Inside proc, a will have the same value as x (at the time of the call) in the calling scope, and similarly b will have the value 7.
If you're trying to call proc and view the result, then there are two things you need to know:
You call a function by typing its name, followed by a pair of parentheses that contains the function's arguments: proc(23, 42)
You can print the result of an expression by typing print, followed by a pair of parentheses containing the expression: print(4 + 8 * sqrt(15) - 26).
Combine these two principles to view the result of a function call.
print(proc(23, 42))
So I have created a function that applies an action (in this case point wise multiplication of an array with a sinusoid, but that does not matter for my question) to an array.
Now I have created another function with which I want to create a string of python code to apply the first function multiple times later-on. The input of the second function can be either a string or an array, so that I can use the second function on its own output as well, if need be. My method of getting the variable name in a string works outside of the function.
Input :
var = np.array([[1,3],[2,4]]) # or sometimes var = 'a string'
if type(var)==str:
var_name = var
else:
var_name = [ k for k,v in locals().items() if v is var][0]
var_name
Output :
'var'
So here var is the variable (either array or string) supplied to the function, in this case an array. The if statement nicely returns me its name.
However when I use this inside my function, no matter what input I give it, it actually seems to look for var in locals(). Somehow it does not take var from the function input.
Definition :
def functionTWO(var, listoflistsofargs=None):
if type(var)==str:
var_name = var
else:
var_name = [ k for k,v in locals().items() if v is var][0]
if listoflistsofargs==None:
return var_name
command = []
for i in range(len(listoflistsofargs)):
if i==0:
command.append('functionONE(')
command.append(var_name)
command.append(',%.17f, %.17f)' % tuple(listoflistsofargs[i]))
else:
command.insert(0,'functionONE(')
command.append(',%.17f, %.17f)' % tuple(listoflistsofargs[i]))
''.join(command)
command[0] = var_name + ' + ' + command[0]
return ''.join(command)
Input :
somearray = np.array([[1,2,3],[1,2,3],[1,2,3]])
args = [[1,3],[6,5]]
command = functionTWO(somearray, args)
command
Output :
NameError: name 'var' is not defined
Wanted output :
'functionONE(functionONE(somearray, 1, 3), 6, 5)'
Why is listoflistsofargs taken from the function input and var not? I specify var in the listcomprehension in the definition of functionTWO. Normally when I use list comprehensions with function inputs it works fine. Does anybody know why this isnt the case here? Thank you in advance!
EDIT : So I guess the answer is dont. The implementation of classes by Marcin looks much cleaner and about the same order of amount of code. Too bad I couldnt get this to work inside a function. For other donts (actually other ideas) about using variable names as strings there is this question, where I got the above list comprehension for variable names.
You cannot pass a variable as a string*, and you should not do so.
If you want to pass a value between functions, the normal way is to pass it in as a parameter, and out as a return value.
If that is inconvenient, the usual solution is an object: define a class which carries both the shared variable, and methods which act on the variable.
If you need to create command objects, it is much better to do so in a structured way. For example, if you want to pass a function, and parameters, you can literally just pass the function object and the parameters in a tuple:
def foo():
return (functionONE,somearray,1,3)
command = foo()
command[0](*command[1:])
If you want to embed such commands within commands, you'll likely want to wrap that up with a class, so you can recursively evaluate the parameters. In fact, here's a little evaluator:
def evaluator(object):
def __init__(self,func=None,params=None):
self.func = func
self.params = params
def eval(self,alternativeparams=None):
if alternativeparams is not None:
params = alternativeparams
else:
params = self.params
if params is not None:
evaluatedparams = (item() if callable(item) else item for item in params)
else: evaluatedparams = None
if func is not None:
return self.func(*(evaluatedparams or ()))
else: return evaluatedparams
def __call__(self, *params):
return self.eval(params if params else None)
Although there are hacks by which you can pass references to local variables out of a function, these are not a great idea, because you end up creating your own half-baked object system which is more difficult to understand.
* This is because a variable has a name (which is a string) and a context, which maps names to strings. So, you need, at least to pass a tuple to truly pass a variable.
presenter's answer works in python 3
def get_variable_name(*variable):
return [ k for k,v in globals().items() if v is variable[0]][0]
example:
>> test = 'sample string'
>> get_variable_name(test)
'test'
>>
The only issue is it is a little messy.
The reason you get the error NameError: name 'var' is not defined when you wrap it all into a function is the following: locals().items() refers to the locally defined variables. as a matter of fact, the locally defined variables in your functions are only the variables defined inside the function and those passed as arguments to the function.
As the name says, locals().items() is local, and will consist of different variables depending on where it is called in your script.
On the contrary globals().items() consists of all the global variables, so try using it instead in your functions, it should do the trick.
For more info, look up global and local variables as well as the scope of variables in Python.
This is a piece of my code...
def contactMaster(data="",url= str(chosenMaster)+"todolist"):
print "url: "+url
It prints only "todolist" instead of "http://www.mysite.com/blah/1234/todolist"
Why isn't it working??
Default arguments are evaluated when the function is defined not when it is executed. So if chosenMaster is empty when Python defines contactMaster, it will print only todolist.
You need to move str(chosenMaster) into the function.
See Default Argument Values in the Python Tutorial for more info. The example there is:
The default values are evaluated at the point of function definition in the defining scope, so that
i = 5
def f(arg=i):
print arg
i = 6
f()
will print 5.
The function definition captures the value of chosenMaster at the time the function is declared, not when the function is called.
Do this instead:
def contactMaster(data='', url=None):
if url is None:
url = str(chosenMaster) + 'todolist'
print 'url: ' + url
Because default function arguments are determined when the function is defined. Changing chosenMaster after the fact will have no effect.