I want to programmatically edit python source code. Basically I want to read a .py file, generate the AST, and then write back the modified python source code (i.e. another .py file).
There are ways to parse/compile python source code using standard python modules, such as ast or compiler. However, I don't think any of them support ways to modify the source code (e.g. delete this function declaration) and then write back the modifying python source code.
UPDATE: The reason I want to do this is I'd like to write a Mutation testing library for python, mostly by deleting statements / expressions, rerunning tests and seeing what breaks.
Pythoscope does this to the test cases it automatically generates as does the 2to3 tool for python 2.6 (it converts python 2.x source into python 3.x source).
Both these tools uses the lib2to3 library which is an implementation of the python parser/compiler machinery that can preserve comments in source when it's round tripped from source -> AST -> source.
The rope project may meet your needs if you want to do more refactoring like transforms.
The ast module is your other option, and there's an older example of how to "unparse" syntax trees back into code (using the parser module). But the ast module is more useful when doing an AST transform on code that is then transformed into a code object.
The redbaron project also may be a good fit (ht Xavier Combelle)
The builtin ast module doesn't seem to have a method to convert back to source. However, the codegen module here provides a pretty printer for the ast that would enable you do do so.
eg.
import ast
import codegen
expr="""
def foo():
print("hello world")
"""
p=ast.parse(expr)
p.body[0].body = [ ast.parse("return 42").body[0] ] # Replace function body with "return 42"
print(codegen.to_source(p))
This will print:
def foo():
return 42
Note that you may lose the exact formatting and comments, as these are not preserved.
However, you may not need to. If all you require is to execute the replaced AST, you can do so simply by calling compile() on the ast, and execing the resulting code object.
Took a while, but Python 3.9 has this:
https://docs.python.org/3.9/whatsnew/3.9.html#ast
https://docs.python.org/3.9/library/ast.html#ast.unparse
ast.unparse(ast_obj)
Unparse an ast.AST object and generate a string with code that would produce an equivalent ast.AST object if parsed back with ast.parse().
In a different answer I suggested using the astor package, but I have since found a more up-to-date AST un-parsing package called astunparse:
>>> import ast
>>> import astunparse
>>> print(astunparse.unparse(ast.parse('def foo(x): return 2 * x')))
def foo(x):
return (2 * x)
I have tested this on Python 3.5.
You might not need to re-generate source code. That's a bit dangerous for me to say, of course, since you have not actually explained why you think you need to generate a .py file full of code; but:
If you want to generate a .py file that people will actually use, maybe so that they can fill out a form and get a useful .py file to insert into their project, then you don't want to change it into an AST and back because you'll lose all formatting (think of the blank lines that make Python so readable by grouping related sets of lines together) (ast nodes have lineno and col_offset attributes) comments. Instead, you'll probably want to use a templating engine (the Django template language, for example, is designed to make templating even text files easy) to customize the .py file, or else use Rick Copeland's MetaPython extension.
If you are trying to make a change during compilation of a module, note that you don't have to go all the way back to text; you can just compile the AST directly instead of turning it back into a .py file.
But in almost any and every case, you are probably trying to do something dynamic that a language like Python actually makes very easy, without writing new .py files! If you expand your question to let us know what you actually want to accomplish, new .py files will probably not be involved in the answer at all; I have seen hundreds of Python projects doing hundreds of real-world things, and not a single one of them needed to ever writer a .py file. So, I must admit, I'm a bit of a skeptic that you've found the first good use-case. :-)
Update: now that you've explained what you're trying to do, I'd be tempted to just operate on the AST anyway. You will want to mutate by removing, not lines of a file (which could result in half-statements that simply die with a SyntaxError), but whole statements — and what better place to do that than in the AST?
Parsing and modifying the code structure is certainly possible with the help of ast module and I will show it in an example in a moment. However, writing back the modified source code is not possible with ast module alone. There are other modules available for this job such as one here.
NOTE: Example below can be treated as an introductory tutorial on the usage of ast module but a more comprehensive guide on using ast module is available here at Green Tree snakes tutorial and official documentation on ast module.
Introduction to ast:
>>> import ast
>>> tree = ast.parse("print 'Hello Python!!'")
>>> exec(compile(tree, filename="<ast>", mode="exec"))
Hello Python!!
You can parse the python code (represented in string) by simply calling the API ast.parse(). This returns the handle to Abstract Syntax Tree (AST) structure. Interestingly you can compile back this structure and execute it as shown above.
Another very useful API is ast.dump() which dumps the whole AST in a string form. It can be used to inspect the tree structure and is very helpful in debugging. For example,
On Python 2.7:
>>> import ast
>>> tree = ast.parse("print 'Hello Python!!'")
>>> ast.dump(tree)
"Module(body=[Print(dest=None, values=[Str(s='Hello Python!!')], nl=True)])"
On Python 3.5:
>>> import ast
>>> tree = ast.parse("print ('Hello Python!!')")
>>> ast.dump(tree)
"Module(body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Str(s='Hello Python!!')], keywords=[]))])"
Notice the difference in syntax for print statement in Python 2.7 vs. Python 3.5 and the difference in type of AST node in respective trees.
How to modify code using ast:
Now, let's a have a look at an example of modification of python code by ast module. The main tool for modifying AST structure is ast.NodeTransformer class. Whenever one needs to modify the AST, he/she needs to subclass from it and write Node Transformation(s) accordingly.
For our example, let's try to write a simple utility which transforms the Python 2 , print statements to Python 3 function calls.
Print statement to Fun call converter utility: print2to3.py:
#!/usr/bin/env python
'''
This utility converts the python (2.7) statements to Python 3 alike function calls before running the code.
USAGE:
python print2to3.py <filename>
'''
import ast
import sys
class P2to3(ast.NodeTransformer):
def visit_Print(self, node):
new_node = ast.Expr(value=ast.Call(func=ast.Name(id='print', ctx=ast.Load()),
args=node.values,
keywords=[], starargs=None, kwargs=None))
ast.copy_location(new_node, node)
return new_node
def main(filename=None):
if not filename:
return
with open(filename, 'r') as fp:
data = fp.readlines()
data = ''.join(data)
tree = ast.parse(data)
print "Converting python 2 print statements to Python 3 function calls"
print "-" * 35
P2to3().visit(tree)
ast.fix_missing_locations(tree)
# print ast.dump(tree)
exec(compile(tree, filename="p23", mode="exec"))
if __name__ == '__main__':
if len(sys.argv) <=1:
print ("\nUSAGE:\n\t print2to3.py <filename>")
sys.exit(1)
else:
main(sys.argv[1])
This utility can be tried on small example file, such as one below, and it should work fine.
Test Input file : py2.py
class A(object):
def __init__(self):
pass
def good():
print "I am good"
main = good
if __name__ == '__main__':
print "I am in main"
main()
Please note that above transformation is only for ast tutorial purpose and in real case scenario one will have to look at all different scenarios such as print " x is %s" % ("Hello Python").
If you are looking at this in 2019, then you can use this libcst
package. It has syntax similar to ast. This works like a charm, and preserve the code structure. It's basically helpful for the project where you have to preserve comments, whitespace, newline etc.
If you don't need to care about the preserving comments, whitespace and others, then the combination of ast and astor works well.
I've created recently quite stable (core is really well tested) and extensible piece of code which generates code from ast tree: https://github.com/paluh/code-formatter .
I'm using my project as a base for a small vim plugin (which I'm using every day), so my goal is to generate really nice and readable python code.
P.S.
I've tried to extend codegen but it's architecture is based on ast.NodeVisitor interface, so formatters (visitor_ methods) are just functions. I've found this structure quite limiting and hard to optimize (in case of long and nested expressions it's easier to keep objects tree and cache some partial results - in other way you can hit exponential complexity if you want to search for best layout). BUT codegen as every piece of mitsuhiko's work (which I've read) is very well written and concise.
One of the other answers recommends codegen, which seems to have been superceded by astor. The version of astor on PyPI (version 0.5 as of this writing) seems to be a little outdated as well, so you can install the development version of astor as follows.
pip install git+https://github.com/berkerpeksag/astor.git#egg=astor
Then you can use astor.to_source to convert a Python AST to human-readable Python source code:
>>> import ast
>>> import astor
>>> print(astor.to_source(ast.parse('def foo(x): return 2 * x')))
def foo(x):
return 2 * x
I have tested this on Python 3.5.
Unfortunately none of the answers above actually met both of these conditions
Preserve the syntactical integrity for the surrounding source code (e.g keeping comments, other sorts of formatting for the rest of the code)
Actually use AST (not CST).
I've recently written a small toolkit to do pure AST based refactorings, called refactor. For example if you want to replace all placeholders with 42, you can simply write a rule like this;
class Replace(Rule):
def match(self, node):
assert isinstance(node, ast.Name)
assert node.id == 'placeholder'
replacement = ast.Constant(42)
return ReplacementAction(node, replacement)
And it will find all acceptable nodes, replace them with the new nodes and generate the final form;
--- test_file.py
+++ test_file.py
## -1,11 +1,11 ##
def main():
- print(placeholder * 3 + 2)
- print(2 + placeholder + 3)
+ print(42 * 3 + 2)
+ print(2 + 42 + 3)
# some commments
- placeholder # maybe other comments
+ 42 # maybe other comments
if something:
other_thing
- print(placeholder)
+ print(42)
if __name__ == "__main__":
main()
We had a similar need, which wasn't solved by other answers here. So we created a library for this, ASTTokens, which takes an AST tree produced with the ast or astroid modules, and marks it with the ranges of text in the original source code.
It doesn't do modifications of code directly, but that's not hard to add on top, since it does tell you the range of text you need to modify.
For example, this wraps a function call in WRAP(...), preserving comments and everything else:
example = """
def foo(): # Test
'''My func'''
log("hello world") # Print
"""
import ast, asttokens
atok = asttokens.ASTTokens(example, parse=True)
call = next(n for n in ast.walk(atok.tree) if isinstance(n, ast.Call))
start, end = atok.get_text_range(call)
print(atok.text[:start] + ('WRAP(%s)' % atok.text[start:end]) + atok.text[end:])
Produces:
def foo(): # Test
'''My func'''
WRAP(log("hello world")) # Print
Hope this helps!
A Program Transformation System is a tool that parses source text, builds ASTs, allows you to modify them using source-to-source transformations ("if you see this pattern, replace it by that pattern"). Such tools are ideal for doing mutation of existing source codes, which are just "if you see this pattern, replace by a pattern variant".
Of course, you need a program transformation engine that can parse the language of interest to you, and still do the pattern-directed transformations. Our DMS Software Reengineering Toolkit is a system that can do that, and handles Python, and a variety of other languages.
See this SO answer for an example of a DMS-parsed AST for Python capturing comments accurately. DMS can make changes to the AST, and regenerate valid text, including the comments. You can ask it to prettyprint the AST, using its own formatting conventions (you can changes these), or do "fidelity printing", which uses the original line and column information to maximally preserve the original layout (some change in layout where new code is inserted is unavoidable).
To implement a "mutation" rule for Python with DMS, you could write the following:
rule mutate_addition(s:sum, p:product):sum->sum =
" \s + \p " -> " \s - \p"
if mutate_this_place(s);
This rule replace "+" with "-" in a syntactically correct way; it operates on the AST and thus won't touch strings or comments that happen to look right. The extra condition on "mutate_this_place" is to let you control how often this occurs; you don't want to mutate every place in the program.
You'd obviously want a bunch more rules like this that detect various code structures, and replace them by the mutated versions. DMS is happy to apply a set of rules. The mutated AST is then prettyprinted.
I used to use baron for this, but have now switched to parso because it's up to date with modern python. It works great.
I also needed this for a mutation tester. It's really quite simple to make one with parso, check out my code at https://github.com/boxed/mutmut
Related
I am trying to do a unit test with Pytest on a function of the form
def function():
with open('file.txt', 'r') as file:
# read for information in file
return information_from_file
I want to make a temporary directory which I can use the function to read from. This lead me to using tmpdir and tmpdir_factory, however both these options require that a path object is inputted as an argument from what I can tell. Though in this case, that isn't an option since the function is reading from the current directory rather than a directory that was inputted.
Is there a way to use Pytest in order to do a test on this kind of function?
You could use mock_open, but that would be a glass-box test breaking the encapsulation of the function. If the filename changes, the test breaks. If it changes its implementation, the test breaks.
More importantly, it ignores what your test is telling you.
Testing is a great way to find out where your design is too rigid. If you find a function hard to test, its probably hard to use. Hard coded filenames are a classic example. This is an opportunity to make the code more flexible. For example, introduce a configuration object.
def function():
with open(MyApp.config('function','file'), 'r') as file:
# read for information in file
return information_from_file
Exactly how this is implemented depends on your situation. You can use Python's built in ConfigParser to work with the config file. And here I've gone with an application singleton object to store application-wide information.
Then you have two tests. One which checks the default MyApp.config('function','file') is as expected. And other which sets MyApp.config('function','file') to a temp file and tests the function reads it.
First of all sorry for my bad english, I am from Germany and currently learning english so please don't be harsh to me.
Now my question is, is there a way to execute a response by a bot on an equation, that turns out correct /equal. So in like an if-else statement
UPDATE - After writing the original answer below, I realized that regular commands would be able to handle many cases if there were a suitable parameter, like $if('expr', 'true-response', 'false-response'). So I wrote one. You can find it at https://github.com/madelsberger/if_StreamlabsParameter
The parameter is itself implemented in a Python script, so you'd still have to set your bot up to use Python scripts. But then if you install this parameter script, you can use it in regular commands instead of implementing each command with yet more custom scripting.
Note that this script is not approved by the Streamlabs Chatbot support (nor am I familiar with a procedure for submitting it to be approved); and I provide it under the MIT license (i.e. "AS IS"). It should work fine, and you're free to review the code to verify I haven't done anything malicious. I'll try to make a reasonable effort to answer reasonable questions as time permits.
So what you want is for the user to issue a command, and then the bot does a calculation; if a particular equation is satisfied, it sends a particular response, and if the equation is not satisfied it sends a different response (or just doesn't send); is that right?
I don't think basic commands (i.e. the Commands tab) can do this. You can do it with custom scripting. The script you need may not be very complicated, but you would need to install Python 2.7.13 and write a little Python code that satisfies the requirements for a Streamlabs Chatbot script.
As a very basic example, say we want to create a "guess my number" game, and when someone guesses it says "Correct" if the guess is correct.
In your chatbot's .../Services/Scripts directory you would create a subdirectory for your script (lets call it guess, and in that folder you would create guess_StreamlabsSystem.py as follows
# chatbot won't load a script that doesn't define these variables
ScriptName = "guess"
Website = None
Description = "number guessing game"
Creator = "madelsberger" # or for a script you write, your name here
Version = "1.0.0"
# global data used by the script
correctNumber = None
# called when your script starts up
def Init():
global correctNumber
correctNumber = Parent.GetRandom(1, 11)
# called whenever the chatbot has data - chat messages, whispers, etc. - that
# your script might care about
def Execute(data):
global correctNumber
if data.IsChatMessage() and data.GetParam(0).lower() == '!guess':
try: # avoid problems if a non-numeric guess is given
if int(data.GetParam(1)) == correctNumber:
Parent.SendTwitchMessage("#" + data.User
+ " guessed correctly!")
correctNumber = Parent.GetRandom(1, 11)
else:
Parent.SendTwitchMessage(data.GetParam(1) + " is not correct")
except:
pass
# called frequently to mark the passage of time; if there's some condition
# your bot wants to act on *other* than data from the bot, and if you can
# write code that watches for that condition, it can go here; but beware this
# gets run frequently, so if the check is resource-intensive then you don't
# want to run it on *every* tick
def Tick():
pass
Note that in practice you might want to add cooldown controls, or permission controls. Your code can see an object called Parent which provides methods to handle these things. You also might want things like the trigger command to be configurable; you can set that up using a UI_Config.json file. See the chatbot docs for more details on scripting. https://cdn.streamlabs.com/chatbot/Documentation.pdf
Can anyone guide me towards the right direction as to where I should place a script solely for loading data into ndb. As I wish to upload all data into the gae ndb so that the application could perform query on it.
Right now, the loading of data is in my application. I wish to placed it separately from the main application.
Should it be edited in the yaml file?
EDITED
This is a snippet of the entity and the handler to upload the data into GAE ndb.
I wish to placed this chunk of code separately from my main application .py. Reason being the uploading of this data won't be done frequently and to keep the codes in the main application "cleaner".
class TagTrend_refine(ndb.Model):
tag = ndb.StringProperty()
trendData = ndb.BlobProperty(compressed=True)
class MigrateData(webapp2.RequestHandler):
def get(self):
listOfEntities = []
f = open("tagTrend_refine.txt")
lines = f.readlines()
f.close()
for line in lines:
temp = line.strip().split("\t")
data = TagTrend_refine(
tag = temp[0],
trendData = temp[1]
)
listOfEntities.append(data)
ndb.put_multi(listOfEntities)
For example if I placed the above code in a file called dataLoader.py, where should I call this script to invoke?
In app.yaml alongside my main application(knowledgeGraph.application)?
- url: /.*
script: knowledgeGraph.application
You don't show us the application object (no doubt a WSGI app) in your knowledge.py module, so I can't know what URL you want to serve with the MigrateData handler -- I'll just guess it's something like /migratedata.
So the class TagTrend_refine should be in a separate file (usually called models.py) so that both your dataloader.py, and your knowledge.py, can import models to access it (and models.py will need its own import of ndb of course). (Then of course access to the entity class will be as models.TagTrend_refine -- very basic Python).
Next, you'll complete dataloader.py by defining a WSGI app, e.g, at end of file,
app = webapp2.WSGIApplication(routes=[('/migratedata', MigrateData)])
(of course this means this module will need to import webapp2 as well -- can I take for granted a knowledge of super-elementary Python?).
In app.yaml, as the first URL, before that /.*, you'll have:
url: /migratedata
script: dataloader.app
Given all this, when you visit '/migratedata', your handler will read the "tagTrend_refine.txt" file that you uploaded together with your .py, .yaml, and so on, files in your overall GAE application, and unconditionally create one entity per line of that file (assuming you fix the multiple indentation problems in your code as displayed above, but, again, this is just super-elementary Python -- presumably you've used both tabs and spaces and they show up OK in your editor, but not here on SO... I recommend you use strictly, only spaces, never tabs, in Python code).
However this does seem to be a peculiar task. If /migratedata gets visited twice, it will create duplicates of all entities. If you change the tagTrend_refine.txt and deploy a changed variation, then visit /migratedata... all old entities will stick around and all the new entities will join them. And so forth.
Moreover -- /migratedata is NOT idempotent (if visited more than once it does not produce the same state as running it just once) so it shouldn't be a GET (and now we're on to super-elementary HTTP for a change!-) -- it should be a POST.
In fact I suspect (but I'm really flying blind here, since you see fit to give such tiny amounts of information) that you in fact want to upload a .txt file to a POST handler and do the updates that way (perhaps avoiding duplicates...?). However, I'm no mind reader, so this is about as far as I can go.
I believe I have fully answered the question you posted (though perhaps not the one you meant but didn't express:-) and by SO's etiquette it would be nice to upvote and accept this answer, then, if needed, post another question, expressing MUCH more clearly and completely what you're trying to achieve, your current .py and .yaml (ideally with correct indentation), what they actually do and why you'd like to do something different. For POST vs GET in particular, just study When should I use GET or POST method? What's the difference between them? ...
Alex's solution will work, as long as all you data can be loaded in under 1 minute, as that's the timeout for an app engine request.
For larger data, consider calling the datastore API directly from your own computer where you have the source. It's a bit of a hassle because it's a different API; it's not ndb. But it's still a pretty simple API. Here's some code that calls the API:
https://github.com/GoogleCloudPlatform/getting-started-python/blob/master/2-structured-data/bookshelf/model_datastore.py
Again, this code can run anywhere. It doesn't need to be uploaded to app engine to run.
I need to call a python script from C#, I'll be doing it like this:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C python \"C:\\working\\projects\\python tests\\Sample Data.py\"";
process.StartInfo = startInfo;
process.Start();
but I now need to add in command line arguments. I'm trying to decide between just using sys.argv which seems very simple to implement or to go with argparse. If I will always pass one and only one parameter (a date), is there any advantage to using argparse?
Additional info regarding the problem (slightly tangential to the question):
The date I'm passing is a parameter for a SQL query. I could instead run this query in C# (which I would prefer) but then I will need to pass the result to python via command line arguments which seems to me to be a terrible idea but maybe this is something argparse can handle? The table has two date columns and 4 float columns. Can such a table be passed this way?
The reason I am calling python via cmd.exe and not using IronPython is (A) I only need to pass information once from C# to Python so the communication between the two is very limited and (B) the result of which is a 3D surface plot generated by mplot3d which seems like a huge hassle to make work in IronPython (which actually generally confuses me anyway), so if I am just passing the single date then this doesn't seem unreasonable. But if I could pass that entire table easily, either by a command line argument or else some other not overly complicated method, I would be very interested in hearing how.
Since you're a nice clean slate of knowledgeless bliss, learn argparse. It's piss-easy and replaces sys.arg which is now considered old, archaic, and (probably) deprecated; although you'll find it far more common, for now, because it's been around since Guido was a baby.
I need to write a piece of software that takes a user-defined function (written in python) as an input.
The user-defined function takes a vector of numbers and returns a vector of numbers.
My software will call this user function many times (in the same way a root search would do) and then returns some result.
The source code of my soft will be written in python (it will use a *.pyd) or in C++ and must be hidden from the user.
What is the best way (if there is any...) to achieve this? Ideally I would have my python code compiled in *.exe and the user would copy-paste his/her function in a text box, but using it from python interpreter should be acceptable, too.
Here's a very limited example which shows how you could do it -- Of course, there are some limitations here -- Mainly, this only works if the user only inputs a single function. If the string they write looks more like:
a='garbage'
def foo():pass
or even:
def bar():
return foobar()
def foobar():
return "foobar is a cool word, don't you think?"
then you're out of luck. (In other words, this assumes that the user is only adding one thing to the namespace of the run_user function). Of course, you could check that and raise an exception or whatever if it turns out the user added too much...You could also return the function and use it as proposed by gauden.
def run_user(S):
#S is the user's function as a string.
lvars=None #make sure the name is in locals()
lvars=set(locals())
exec(S) #exec isn't usually a good idea -- but I guess you're a very trusting person.
usr_namespace=list(set(locals())-lvars)
usr_func_name=usr_namespace[0]
if(len(usr_namespace)>1):
raise ValueError("User input too much into the namespace!")
usr_func=locals()[usr_func_name]
usr_func() #comment this out if you don't want to run the function immediately
return usr_func
usr_string="""
def foo():
a="Blah"
print "Hello World! "+a
"""
func_handle=run_user(usr_string) #prints "Hello World! Blah"
#and to demonstrate that we can pass a handle to the function around:...
func_handle() #prints "Hello World! Blah" again.
Note that you could do this a little more safely using python 3's exec or python 2's execfile where you could limit the namespace of the user's function by passing the dictionary {'__builtins__':None} as the global dictionary
#python3.x
allowed=vars(__builtins__).copy()
allowed['__import__']=None
exec("import os",{'__builtins__':None},allowed) #raises ImportError
exec("print(abs(-4))",{'__builtins__':None},allowed) #prints 4 as you'd expect.
I would expect the same thing to work with execfile under python2.x provided you wrote the string to a temporary file...
EDIT (to address the comments below)
The example that you provide with eval could be done a little more simply:
a=5
b=eval('a+5') #b == 10
However, this isn't what you asked for. What you asked for was that the user could write a function, e.g.:
def f(a):
return a+5
The former case will work, but the user needs to know that the variable name is 'a'.
a=5
b=eval('x+5') #won't work -- x isn't defined
They also need to know how to add the vectors -- (If you're using numpy arrays that's trivial, but I thought I would mention it just in case you're not). And, they can't make complex expressions (long expressions using multiple conditionals, loops, etc.) without a decent amount of work and head-scratching.
The latter case is a little better (in my opinion) because it is much more general. You can get the function using the method I described (removing the part in there where I actually run the function) and the user can use any variable name(s) they want -- then you just use their function. They can also do things like loops, and use expressions that are much more complex than you could do in a single line with eval. The only thing you pay for this is that the user needs to write def func(...): and return some_value at the end of it which if they know python should be completely intuitive.
ss="""
def foo(x):
return 5+x
"""
a=5
func=run_user(ss)
result=func(a) #result = 10
This also has the advantage that the string doesn't need to be re-parsed every time you want to call the function. Once you have func, you can use it however/whenever you want. Also note that with my solution, you don't even need to know the name of the function the user defined. Once you have the function object, the name is irrelevant.