Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
167 views
in Technique[技术] by (71.8m points)

True dynamic and anonymous functions possible in Python?

Just as a dynamic class can be created using type(name, base-classes, namespace-dict), can a dynamic function be created?

I've tried doing something along the lines of:

>>> f = type("f", (function,), {})
NameError: name 'function' is not defined

Ok, so I'll be clever, but:

>>> def fn():
...   pass
... 
>>> type(fn)
<type 'function'>
>>> f = type("f", (type(fn),), {})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type 'function' is not an acceptable base type

Does Python specifically prevent the creation of dynamic functions in the same way it allows dynamic classes?

Edit: Note, I'd disallow any use of exec.. Since my question is does the Python language itself permit this.

Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is types.FunctionType which you can use to dynamically create a function e.g.

def test_func(): print 'wow' 
dynf = types.FunctionType(test_func.func_code, {})
dynf()

Output:

wow

You might object that this is not dynamic because I am using code from another function, but that was just an example there is a way to generate code from python strings e.g.

dynf = types.FunctionType(compile('print "really WoW"', 'dyn.py', 'exec'), {})
dynf()

Output:

really WoW

Now that is dynamic!

OP is worried about the dynamic nature of such function so here is another example

dynf = types.FunctionType(compile('test_func():
test_func()', 'dyn.py', 'exec'), globals())
dynf()

Output:

wow
wow

Note: Creating Function object like this seems to have limitations e.g. it is not easy to pass arguments, because to pass arguments we need to pass correct co_argcount, co_varnames and other 12 variables to types.CodeType, which theoretically can be done but will be error prone, an easier way is to import string as a module and you have a full fledged function e.g.

import types
import sys,imp

code = """def f(a,b,c):
    print a+b+c, "really WoW"
"""
module = imp.new_module('myfunctions')
exec code in module.__dict__
module.f('W', 'o', 'W')

Output:

WoW really WoW

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...