I want to basically turn a list element into a function with
the do function. This way any pre-written funcction i can call by just use a
do(list[x]).
What im trying to do is a function that takes away the quotes of a list element and then executes the function that is in that list element.
def func():
print "python"
def func1():
print "is"
def func2():
print "awesome"
def do(fun):
fun()
#I think the problem is here
funs = ['func()','func1()','func2()']
print ''.join(funs[0])
do(''.join(funs[0]))
Edit:
What im trying to do is a function that takes away the quotes of a
list element and then executes the function that is in that list
element
You don't need the extra functions, and you don't need to turn them into a string either:
def func():
print "python"
def func1():
print "is"
def func2():
print "awesome"
funcs = [func, func1, func2]
for function in funcs:
function()
Well, it basically works like this. Note that the list contains the functions themselves, not a string.
def func():
print "python"
def func1():
print "is"
def func2():
print "awesome"
def do(fun):
fun()
funcs = [func, func1, func2]
for function in funcs:
do(function)
Output:
python
is
awesome
EDIT: If you do want the list to contain the functions' names as strings, use eval():
funcs = ['func', 'func1', 'func2']
for function in funcs:
do(eval(function))
If you really want to execute arbitrarily named functions from a list of names in the current global/module scope then this will do:
NB: This does NOT use the potentially unsafe and dangerous eval():
Example:
def func():
return "python"
def func1():
return "is"
def func2():
return "awesome"
def do(func_name, *args, **kwargs):
f = globals().get(func_name, lambda : None)
if callable(f):
return f(*args, **kwargs)
funs = ["func", "func1", "func2"]
print "".join(funs[0])
print "".join(map(do, funs))
Output:
$ python foo.py
func
pythonisawesome
You can also individually call "named" functions:
>>> do(funs[0])
python
Note the implementation of do(). This could also be applied more generically on objects and other modules too swapping out globals() lookups.
As the people above have said the best way is to define a dictionary of functions, as functions are objects in python this is possible
def One():
pass
def Two():
pass
functions = {"ONE":One, "TWO":Two}
You can then call it like this:
functions[input]()
If you want to give true control to the user (And I DO NOT recommend doing this) you could use the eval function.
eval(input+"()")
Related
I have a function func :
def func(a):
print a
func.__name_ = "My_Function"
To get the name of the function I will just do func.__name__.
But is there a way to call func() by using its name i.e. "My_Function"?
Edit: There are going to be large number of functions for which this has to be done. Is there any better solution apart from keeping a mapping of function.name to the function. ?
It will be much easier to use a dictionary:
def func():
print('func')
func_dict = {"My_Function": func}
func_dict["My_Function"]()
# 'func'
Assuming that you want to access functions that are defined in global scope (not part of any class/object):
def foo():
print "foo"
def bar():
print "bar"
foo.__name__ = "1"
bar.__name__ = "2"
# locals().items() will return the current local symbol table, which is an iterable and
# it contains the globally defined functions.
symbol_table = locals().items()
# we will generate a list of functions that their __name__ == "1"
one_functions = [value for key, value in symbol_table if callable(value) and value.__name__ == "1"]
# now we can call the first item on the list - foo()
one_functions[0]()
I am using this way of decorating all methods
import inspect
def decallmethods(decorator, prefix='test_'):
def dectheclass(cls):
for name, m in inspect.getmembers(cls, inspect.ismethod):
if name.startswith(prefix):
setattr(cls, name, decorator(m))
return cls
return dectheclass
#decallmethods(login_testuser)
class TestCase(object):
def setUp(self):
pass
def test_1(self):
print "test_1()"
def test_2(self):
print "test_2()"
This is working but it applies at the top , if i have other decorators.
I mean
Now the result is
#login_testuser
#other
def test_2(self):
print "test_2()"
But i want
#other
#login_testuser
def test_2(self):
print "test_2()"
This is most certainly a bad idea, but what you want to do can be done in some extent, and this is going to take a lot of time to explain. First off, rather than thinking of decorators as a syntax sugar, think of them as what they really are: a function (that is a closure) with a function that exist inside it. Now this is out of the way, supposed we have a function:
def operation(a, b):
print('doing operation')
return a + b
Simply it will do this
>>> hi = operation('hello', 'world')
doing operation
>>> print(hi)
helloworld
Now define a decorator that prints something before and after calling its inner function (equivalent to the other decorator that you want to decorator later):
def other(f):
def other_inner(*a, **kw):
print('other start')
result = f(*a, **kw)
print('other finish')
return result
return other_inner
With that, build a new function and decorator
#other
def o_operation(a, b):
print('doing operation')
return a + b
Remembering, this is basically equivalent to o_operation = other(operation)
Run this to ensure it works:
>>> r2 = o_operation('some', 'inner')
other start
doing operation
other finish
>>> print(r2)
someinner
Finally, the final decorator you want to call immediately before operation but not d_operation, but with your existing code it results in this:
def inject(f):
def injected(*a, **kw):
print('inject start')
result = f(*a, **kw)
print('inject finish')
return result
return injected
#inject
#other
def i_o_operation(a, b):
print('doing operation')
return a + b
Run the above:
>>> i_o_operation('hello', 'foo')
inject start
other start
doing operation
other finish
inject finish
'hellofoo'
As mentioned decorators are really closures and hence that's why it's possible to have items inside that are effectively instanced inside. You can reach them by going through the __closure__ attribute:
>>> i_o_operation.__closure__
(<cell at 0x7fc0eabd1fd8: function object at 0x7fc0eabce7d0>,)
>>> i_o_operation.__closure__[0].cell_contents
<function other_inner at 0x7fc0eabce7d0>
>>> print(i_o_operation.__closure__[0].cell_contents('a', 'b'))
other start
doing operation
other finish
ab
See how this effectively calls the function inside the injected closure directly, as if that got unwrapped. What if that closure can be replaced with the one that did the injection? For all of our protection, __closure__ and cell.cell_contents are read-only. What needs to be done is to construct completely new functions with the intended closures by making use of the FunctionType function constructor (found in the types module)
Back to the problem. Since what we have now is:
i_o_operation = inject(other(operation))
And what we want is
o_i_operation = other(inject(operation))
We effectively have to somehow strip the call to other from i_o_operation and somehow wrap it around with inject to produce o_i_operation. (Dragons follows after the break)
First, construct a function that effectively calls inject(operation) by taking the closure to level deep (so that f will contain just the original operation call) but mix it with the code produced by inject(f):
i_operation = FunctionType(
i_o_operation.__code__,
globals=globals(),
closure=i_o_operation.__closure__[0].cell_contents.__closure__,
)
Since i_o_operation is the result of inject(f) we can take that code to produce a new function. The globals is a formality that's required, and finally take the closure of the nested level, and the first part of the function is produced. Verify that the other is not called.
>>> i_operation('test', 'strip')
inject start
doing operation
inject finish
'teststrip'
Neat. However we still want the other to be wrapped outside of this to finally produce o_i_operation. We do need to somehow put this new function we produced in a closure, and a way to do this is to create a surrogate function that produce one
def closure(f):
def surrogate(*a, **kw):
return f(*a, **kw)
return surrogate
And simply use it to construct and extract our closure
o_i_operation = FunctionType(
i_o_operation.__closure__[0].cell_contents.__code__,
globals=globals(),
closure=closure(i_operation).__closure__,
)
Call this:
>>> o_i_operation('job', 'complete')
other start
inject start
doing operation
inject finish
other finish
'jobcomplete'
Looks like we finally got what we need. While this doesn't exactly answer your exact problem, this started down the right track but is already pretty hairy.
Now for the actual problem: a function that will ensure a decorator function be the most inner (final) callable before a given original, undecorated function - i.e. for a given target and a f(g(...(callable)), we want to emulate a result that gives f(g(...(target(callable)))). This is the code:
from types import FunctionType
def strip_decorators(f):
"""
Strip all decorators from f. Assumes each are functions with a
closure with a first cell being the target function.
"""
# list of not the actual decorator, but the returned functions
decorators = []
while f.__closure__:
# Assume first item is the target method
decorators.append(f)
f = f.__closure__[0].cell_contents
return decorators, f
def inject_decorator(decorator, f):
"""
Inject a decorator to the most inner function within the stack of
closures in `f`.
"""
def closure(f):
def surrogate(*a, **kw):
return f(*a, **kw)
return surrogate
decorators, target_f = strip_decorators(f)
result = decorator(target_f)
while decorators:
# pop out the last one in
decorator = decorators.pop()
result = FunctionType(
decorator.__code__,
globals=globals(),
closure=closure(result).__closure__,
)
return result
To test this, we use a typical example use-case - html tags.
def italics(f):
def i(s):
return '<i>' + f(s) + '</i>'
return i
def bold(f):
def b(s):
return '<b>' + f(s) + '</b>'
return b
def underline(f):
def u(s):
return '<u>' + f(s) + '</u>'
return u
#italics
#bold
def hi(s):
return s
Running the test.
>>> hi('hello')
'<i><b>hello</b></i>'
Our target is to inject the underline decorator (specifically the u(hi) callable) into the most inner closure. This can be done like so, with the function we have defined above:
>>> hi_u = inject_decorator(underline, hi)
>>> hi_u('hello')
'<i><b><u>hello</u></b></i>'
Works with undecorated functions:
>>> def pp(s):
... return s
...
>>> pp_b = inject_decorator(bold, pp)
>>> pp_b('hello')
'<b>hello</b>'
A major assumption was made for this first-cut version of the rewriter, which is that all decorators in the chain only have a closure length of one, that one element being the function being decorated with. Take this decorator for instance:
def prefix(p):
def decorator(f):
def inner(*args, **kwargs):
new_args = [p + a for a in args]
return f(*new_args, **kwargs)
return inner
return decorator
Example usage:
>>> #prefix('++')
... def prefix_hi(s):
... return s
...
>>> prefix_hi('test')
'++test'
Now try to inject a bold decorator like so:
>>> prefix_hi_bold = inject_decorator(bold, prefix_hi)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 18, in inject_decorator
ValueError: inner requires closure of length 2, not 1
This is simply because the closure formed by decorator within prefix has two elements, one being the prefix string p and the second being the actual function, and inner being nested inside that expects both those to be present inside its closure. Resolving that will require more code to analyse and reconstruct the details.
Anyway, this explanation took quite a bit of time and words, so I hope you understand this and maybe get you started on the actual right track.
If you want to turn inject_decorator into a decorator, and/or mix it into your class decorator, best of luck, most of the hard work is already done.
Suppose I had two functions within another function like so:
def FooBar(isTheWorldRound = True):
def Foo():
print("Hi, I'm foo.")
def Bar():
print("Hi, I'm bar.")
theFunction = None
if (isTheWorldRound):
return Bar
else:
return [Bar, Foo]
So, I can do this:
myFunction = FooBar(False)
myFunction()
>>> Hi, I'm Bar
>>> Hi, I'm Foo
Concerning this example I have two questions:
What is the proper way to perform the commented line?
Is there a way I can do this without explicitly defining Foo?
Putting two functions into a list gives you just that; a list of functions. It does not make a new function that calls both of the previous functions. For that, you need to define a new wrapper function, e.g.:
def call_all(*funcs):
"""Create a new wrapper to call each function in turn."""
def wrapper(*args, **kwargs):
"""Call the functions and return a list of their outputs."""
return [func(*args, **kwargs) for func in funcs]
return wrapper
(if the * syntax is unfamiliar, see What does ** (double star) and * (star) do for parameters?), which you can now use like:
theFunction = call_all(Bar, Foo)
Note also that:
theFunction = None
if (isTheWorldRound):
return Bar
else:
return [Bar, Foo]
is a bit awkward, I would write it as:
if isTheWorldRound:
return Bar
return [Bar, Foo]
You should also rename the functions/variables per the style guide.
You can certainly compose a new function in a way FooBar will return a single function that evaluates one or both of them.
Consider this:
def F():
funcs = [Foo, Bar]
ret = None
for f in funcs:
ret = f()
return ret
You can make a closure in your FooBar to return a single composition:
def FooBar(isTheWorldRound = True):
if (isTheWorldRound):
funcs = [Bar]
else:
funcs = [Bar, Foo]
def theFunction():
ret = None
for f in funcs:
ret = f()
return ret
return theFunction
Luckily this is easy in Python where functions are first-class objects.
Edit: seems you want to execute the functions directly during the execution of FooBar. Then you can ditch the closure but still call all the functions in a loop.
Replace the commented line with:
return lambda: [None, Foo(), Bar()][0]
It will work as expected:
>>> myFunction = FooBar(False)
>>> myFunction()
Hi, I'm foo.
Hi, I'm bar.
What it does is creating an anonymous function, calling both Foo() and Bar() when invoked, and returning None.
Actually, that should work. Without the parentheses, it's a function pointer (or whatever Python's equivalent is).
To call it, you'd do something like:
theFunction[0]()
To get the 0th function in the list, then apply the parentheses (or any arguments if needed).
I'm trying to shuffle an array of functions in python. My code goes like this:
import random
def func1():
...
def func2():
...
def func3():
...
x=[func1,func2,func3]
y=random.shuffle(x)
And I think it might be working, the thing is that I don't know how to call the functions after I shuffle the array!
if I write "y" after the last line, it doesn't do anything!
Thanks
Firstly, random.shuffle() shuffles the list in place. It does not return the shuffled list, so y = None. That is why it does nothing when you type y.
To call each function, you can loop through x and call each function like so:
for function in x:
function() # The parentheses call the function
Lastly, your functions actually produce a SyntaxError. If you want them to do nothing, add pass at the end of them. pass does absolutely nothing and is put where python expects something.
So altogether:
def func1():
pass
def func2():
pass
def func3():
pass
x = [func1, func2, func3]
random.shuffle(x)
for function in x:
function()
Suppose I have
#someDecorator
def func():
'''this function does something'''
print 1
Now, the object func is an instance of someDecorator. Is there some way I can access the function it holds, i.e something like func.getInnerFunction().
For instance, if I need to retrieve the doc string of func().
See functools.wraps: http://docs.python.org/library/functools.html. The decorator gets the name and doc string of the original function. You use it like this:
def decorator(f):
#functools.wraps(f)
def wrapper():
....
SilentGhost and sri have partial answers for how to deal with this. But the general answer is no: there is no way to get the "wrapped" function out of a decorated function because there is no requirement that the decorator wrap the function in the first place. It may very well have returned an entirely unrelated function, and any references to your original may have already been garbage collected.
Are you looking for something along these lines?
>>> def dec(f):
def inner():
print(f.__doc__)
return inner
>>> #dec
def test():
"""abc"""
print(1)
>>> test()
abc
You're passing function explicitly to the decorator, of course you can access it.
You can attach the wrapped function to the inner function
In [1]: def wrapper(f):
...: def inner():
...: print "inner"
...: inner._orig = f
...: return inner
...:
In [2]: #wrapper
...: def foo():
...: print "foo"
...:
...:
In [3]: foo()
inner
In [4]: foo._orig()
foo
You can try using the undecorated library:
With your example func, you could simply do this to return the original function:
undecorated(func)