Tim*_*mmy 17 python metaprogramming
如何在现有函数之前或之后添加代码?
例如,我有一个班级:
class A(object):
def test(self):
print "here"
Run Code Online (Sandbox Code Playgroud)
我如何编辑类机智元编程,以便我这样做
class A(object):
def test(self):
print "here"
print "and here"
Run Code Online (Sandbox Code Playgroud)
也许某种方式附加另一个功能来测试?
添加另一个功能,如
def test2(self):
print "and here"
Run Code Online (Sandbox Code Playgroud)
并将原始更改为
class A(object):
def test(self):
print "here"
self.test2()
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?
Dan*_*olo 22
如果需要,可以使用装饰器修改函数.但是,由于它不是在函数的初始定义时应用的装饰器,因此您将无法使用@语法糖来应用它.
>>> class A(object):
... def test(self):
... print "orig"
...
>>> first_a = A()
>>> first_a.test()
orig
>>> def decorated_test(fn):
... def new_test(*args, **kwargs):
... fn(*args, **kwargs)
... print "new"
... return new_test
...
>>> A.test = decorated_test(A.test)
>>> new_a = A()
>>> new_a.test()
orig
new
>>> first_a.test()
orig
new
Run Code Online (Sandbox Code Playgroud)
请注意,它也将修改现有实例的方法.
编辑:使用和修改装饰器的args列表到更好的版本argskwargs
Eli*_*ght 10
from functools import wraps
def add_message(func):
@wraps
def with_additional_message(*args, **kwargs)
try:
return func(*args, **kwargs)
finally:
print "and here"
return with_additional_message
class A:
@add_message
def test(self):
print "here"
Run Code Online (Sandbox Code Playgroud)
当然,这实际上取决于你想要完成的事情.我经常使用装饰器,但如果我想做的就是打印额外的消息,我可能会做类似的事情
class A:
def __init__(self):
self.messages = ["here"]
def test(self):
for message in self.messages:
print message
a = A()
a.test() # prints "here"
a.messages.append("and here")
a.test() # prints "here" then "and here"
Run Code Online (Sandbox Code Playgroud)
这不需要元编程,但是你的例子可能会从你真正需要做的事情中大大简化.也许如果您发布有关您的特定需求的更多细节,我们可以更好地建议Pythonic方法.
编辑:因为看起来你想要调用函数,你可以有一个函数列表而不是消息列表.例如:
class A:
def __init__(self):
self.funcs = []
def test(self):
print "here"
for func in self.funcs:
func()
def test2():
print "and here"
a = A()
a.funcs.append(test2)
a.test() # prints "here" then "and here"
Run Code Online (Sandbox Code Playgroud)
请注意,如果要添加将由所有实例调用的函数,A则应创建funcs类字段而不是实例字段,例如
class A:
funcs = []
def test(self):
print "here"
for func in self.funcs:
func()
def test2():
print "and here"
A.funcs.append(test2)
a = A()
a.test() # print "here" then "and here"
Run Code Online (Sandbox Code Playgroud)
此答案允许您在不创建包装器的情况下修改原始函数。我发现了以下两种原生 python 类型,它们对回答您的问题很有用:
types.FunctionType
Run Code Online (Sandbox Code Playgroud)
和
types.CodeType
Run Code Online (Sandbox Code Playgroud)
这段代码似乎可以完成这项工作:
import inspect
import copy
import types
import dill
import dill.source
#Define a function we want to modify:
def test():
print "Here"
#Run the function to check output
print '\n\nRunning Function...'
test()
#>>> Here
#Get the source code for the test function:
testSource = dill.source.getsource(test)
print '\n\ntestSource:'
print testSource
#Take the inner part of the source code and modify it how we want:
newtestinnersource = ''
testSourceLines = testSource.split('\n')
linenumber = 0
for line in testSourceLines:
if (linenumber > 0):
if (len(line[4:]) > 0):
newtestinnersource += line[4:] + '\n'
linenumber += 1
newtestinnersource += 'print "Here2"'
print '\n\nnewtestinnersource'
print newtestinnersource
#Re-assign the function's code to be a compiled version of the `innersource`
code_obj = compile(newtestinnersource, '<string>', 'exec')
test.__code__ = copy.deepcopy(code_obj)
print '\n\nRunning Modified Function...'
test() #<- NOW HAS MODIFIED SOURCE CODE, AND PERFORMS NEW TASK
#>>>Here
#>>>Here2
Run Code Online (Sandbox Code Playgroud)
TODO:
更改此答案以dill.source.getsource获得正确的新源代码。
| 归档时间: |
|
| 查看次数: |
12369 次 |
| 最近记录: |