问题
Perhaps I'm not using the proper term, but I'm looking to take a block of Python code (in Python), get the token tree for the code, make some kind of modification, and re-assemble it to Python.
For instance, consider this block of code:
def x(y):
b = 2
if y == b:
foo(y)
I would like to be able to take this and programmatically do this:
def x(y):
b = 2
if y == b:
bar(y)
I can't imagine that there's not a library that does something like this. Thanks in advance.
EDIT
Perhaps I wasn't entirely clear. I'm looking for a tool to read and manipulate arbitrary code, not code that I'm writing. I'd like to be able to modify code on-the-fly. The project I'm working on is a test app: it uses the Netflix philosophy to try to randomly break the functionality of an app in as many ways as it can, running the test suite each time. When the tests don't fail, there's an indication that there's either a gap in code coverage and/or the code is dead.
回答1:
I was curious about this so I looked into the link Apalala posted, here is what I came up with:
from token import NAME
from tokenize import generate_tokens, untokenize
from StringIO import StringIO
source = """def x(y):
b = 2
if y == b:
foo(y)"""
result = []
tokens = generate_tokens(StringIO(source).readline)
for toknum, tokval, _, _, _ in tokens:
if toknum == NAME and tokval == "foo":
tokval = "bar"
result.append((toknum, tokval))
print untokenize(result)
And the result is:
def x (y ):
b =2
if y ==b :
bar (y )
Yeah I know, the spacing is ugly. I could not figure out how to maintain the format from the original code, but as far as functionality goes, this does what you want.
回答2:
In Python functions can be passed just like any other object so you should be able to do something like:
def x(fx, y):
b = 2
if y == b:
fx(y)
and then call:
x(foo, y)
or
x(bar, y)
Here's a stripped down, tested snippet (v 3.1) that demonstrates the concept w/o any bizlogic, just sample execution and arbitrary numeric manipulation:
def x(fx, y): return fx(y)
def foo(x): return x
def bar(x): return x+1
print(x(foo,1))
print(x(bar,1))
output:
>>>
1
2
回答3:
You can change your program classes by reflection like this
class A(object):
def __init__(self, x):
self.x = x
def show(self):
print self.x
def chglobals():
import newmod
reload(newmod)
o = newmod.A(0)
globals()['A'] = o.__class__
def main():
a = A(10)
a.show()
#change and wirte new code
src = inspect.getsource(a.__class__)
src = src.replace("print self.x", 'print "foo" ')
text_file = open("newmod.py", "w")
text_file.write(src)
text_file.close()
chglobals()
#new istances
b = A(20)
b.show()
#convert old istances
a.__class__ = b.__class__
a.show()
main()
回答4:
I'm going to have to guess about the usecase here, but I'll assume that at a certain point in time you want to switch for 1 function to the other. Doing this can be done relatively easily be using a dictionary filled with functions. For example:
def foo(x): return x
def bar(b): return x+1
fn = { 'foo': foo, 'bar': bar }
def x(y):
b = 2
func = 'foo'
if y == b:
fn[func](y)
This will let you choose which function you want based simply on the dictionary key. You can do so simply by changing the value of func
(for example to 'bar').
来源:https://stackoverflow.com/questions/4764480/python-code-reflection-and-modification