Python中如何在执行类方法前获取方法入参并进行修改
请教个问题,感谢~ 问题:C1 类如何改动,调用 c1.swimming()时 等同于 调用 c1.swimming(c1.add_punctuation( ))。
class C(object):
def __init__(self):
self.name = 'zhangsan '
def swimming(self, action):
return self.name + action
class C1©:
def add_punctuation(self, text):
return ‘:’ + text
c1 = C1()
print c1.swimming(c1.add_punctuation(‘swimming’)) # >zhangsan :swimming
print c1.swimming(‘swimming’) # >zhangsan swimming
Python中如何在执行类方法前获取方法入参并进行修改
inspect package
functools.partial
在Python里,要在执行类方法前获取并修改入参,最直接的方式是使用装饰器或者重写类的__getattribute__方法。不过,__getattribute__会拦截所有属性访问,用起来比较重,通常更推荐用装饰器,这样更清晰、更可控。
下面我给你写个装饰器的例子,它能在方法执行前打印出入参,并且还能让你修改这些参数:
import functools
def intercept_and_modify_args(func):
"""
一个装饰器,用于在方法执行前拦截并修改其入参。
"""
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
# 1. 获取原始入参
print(f"方法 '{func.__name__}' 被调用。")
print(f" 原始位置参数: {args}")
print(f" 原始关键字参数: {kwargs}")
# 2. 在这里你可以修改参数
# 例如,我们把所有位置参数都转成字符串,并给关键字参数加个前缀
modified_args = [str(arg) for arg in args]
modified_kwargs = {f"modified_{key}": value for key, value in kwargs.items()}
print(f" 修改后的位置参数: {modified_args}")
print(f" 修改后的关键字参数: {modified_kwargs}")
# 3. 用修改后的参数调用原方法
return func(self, *modified_args, **modified_kwargs)
return wrapper
class MyClass:
@intercept_and_modify_args
def my_method(self, a, b, name=None):
print(f" 方法内部执行: a={a}, b={b}, name={name}")
return f"Result: {a}, {b}, {name}"
# 测试一下
obj = MyClass()
result = obj.my_method(42, 3.14, name="Alice")
print(f"最终结果: {result}")
运行这段代码,你会看到类似这样的输出:
方法 'my_method' 被调用。
原始位置参数: (42, 3.14)
原始关键字参数: {'name': 'Alice'}
修改后的位置参数: ['42', '3.14']
修改后的关键字参数: {'modified_name': 'Alice'}
方法内部执行: a=42, b=3.14, name=Alice
最终结果: Result: 42, 3.14, Alice
这个装饰器intercept_and_modify_args干了三件事:1)拿到原始参数;2)按你的需求改参数(例子里是把位置参数转字符串、给关键字参数加前缀);3)用改好的参数去调原方法。你只要把它加到想拦截的方法上就行,比如用@intercept_and_modify_args装饰my_method。
如果你需要对一个类里的所有方法都这么处理,可以考虑用类装饰器或者元类,但那样会复杂不少。对于大多数情况,单个方法加装饰器就够用了,简单又灵活。
总结:用装饰器来拦截和修改方法入参最靠谱。
感谢回复!!抱歉我的问题可能没说清楚。我想实现的效果是:python<br><br>c1.swimming(c1.add_punctuation('swimming'))<br>c1.swimming('swimming')<br>#他们调用时等同<br><br>
那就在 C1 里面 override swimming 函数就行了
感谢你的回复。目前遇到的问题是 C 是工具类,内部有很多方法。C1 继承 C,C1 是调用类,使用 C1 调用 C 方法,参数必须需要处理一下。override 是不是太复杂了,因为 C 有很多方法
你要做的就是修改 swimming 的实现,使用 override 不是最简单的么,看不出哪里复杂:
def swimming(self, action):
return C.swimming(self, self.add_punctuation(action)) # 或者 return super(C1, self).swimming(self.add_punctuation(action))
如果你有一堆方法需要修改参数,先写一个 decorator,用处是计算并传递新参数;然后再写个 metaclass,对满足要求的方法都应用上这个 decorator。
因为你写的例子里面,override 是可行的。
但是在真正的项目里面复杂很多,所以你可以考虑下 override getattribute 这个函数。
非常感谢两位,提供思路!!

