python - In Python, how do I change/insert code of a method by other objects/functions/methods
问题描述
I am not new to python but I am far from being an expert (or intermediate). Right now, I play around with objects and their behavior (like setattr, monkey-patch, etc.). During this, I stumbled upon a problem where I do not have any idea on how this might work.
Imagine following code:
class MyCalculator():
def __init__(self):
pass
def addition(self, a, b):
return a + b
def substraction(self, a, b):
return a - b
import inspect
class Changing():
def __init__(self):
pass
def listUserMethods(self, myObject):
object_names = [object_name for object_name in inspect.getmembers(myObject) if (inspect.ismethod(object_name[1]))]
return object_names
def setMethodAttribute(self, myMethod):
pass
if __name__=="__main__":
myCalc = MyCalculator()
change = Changing()
Now, I would like that setMethodAttribute() will change the code of the method I provide itself. Like, inserting a print() statement before the rest of the original method is executed. E.g. printing the input parameter before executing the addition, etc. In my case, this does not need to be done during runtime (even if this is very interesting to know). I could imagine, that using inheritance or something similar could be a way. Perhaps somebody has a great idea?
Thanks for the help!
解决方案
The answer really depends what you are after.
Wrapping a method of a class (before runtime)
This is very typical use case of decorators (the @something
above a function definition).
def with_printing(func):
def wrapper(*args, **kwargs):
print("Before calling method")
ret = func(*args, **kwargs)
print("After calling method")
return ret
return wrapper
class MyCalculator:
@with_printing
def addition(self, a, b):
print("calling addition")
return a + b
If you want to keep the docstring of the original method, you would use the functools.wraps()
.
Example output
mycalc = MyCalculator()
print(mycalc.addition(2, 3))
would print
Before calling method
calling addition
After calling method
5
Wrapping a method of an object instance (runtime)
Here is one implementation which changes the method of an object. Note that this changes the method of an instance and not every instance of that class.
class MyCalculator:
def addition(self, a, b):
print("calling addition")
return a + b
class Changing:
def set_method_attribute(self, obj, method_name):
method = getattr(obj, method_name)
def wrapper(*args, **kwargs):
print("Before calling method")
ret = method(*args, **kwargs)
print("After calling method")
return ret
setattr(obj, method_name, wrapper)
Example usage
# Create two calculator objects for testing
mycalc = MyCalculator()
mycalc2 = MyCalculator()
change = Changing()
# Before change
print(mycalc.addition(2, 3))
print("----")
# After change
change.set_method_attribute(mycalc, "addition")
print(mycalc.addition(2, 3))
print("----")
# The another calculator object remains unchanged
print(mycalc2.addition(2, 3))
will print
calling addition
5
----
Before calling method
calling addition
After calling method
5
----
calling addition
5
推荐阅读
- sql-server - 如何获得前几个月的名字
- javascript - 有什么功能可以读取(excel文件)中的多张纸吗?
- python-imaging-library - python枕头增加gif文件大小x10
- reactjs - 身份验证完成前受保护的路由重定向
- jmeter-5.0 - 如果我们通过 HTTPS 代理服务器记录脚本,我们如何在 jmeter 中获取记录日志?
- django - 根据周数注释查询的响应
- c# - 如何在 WQL 中定位多个远程节点?
- python - 使用 boto3 从 s3 下载时使用文件名作为文件名
- python - 如何重新索引重新采样的 Pandas DataFrame,其中缺少日期以保持当前值
- windows - 重命名自动添加的隐藏扩展