Python中传递方法参数到类时的可调用对象提前求值问题
问题:传递类方法/属性时被提前求值
嘿,我完全懂你的痛点——当你想把SomeClass.some_method作为参数传给SomeFunction时,它居然直接提前执行了,而不是以一个可调用的引用形式传递过去,对吧?先把你的代码和问题场景理清楚:
你的代码定义
class SomeClass(object): def __init__(self, expr, return_status): self._expr = expr self._status = return_status def __call__(self): if self._expr == self._status: return True def __str__(self): return ("Function: %s\n Return Status: %s\n" % (self.__class__.__name__, self._status)) # 问题调用语句:这里的SomeClass.some_method被提前求值了 some_variable = SomeFunction(SomeClass.some_method, return_status=True)
为什么会出现这个问题?
最常见的原因有两个:
some_method是用@property装饰的属性:当你访问SomeClass.some_method(哪怕不带括号),Python会自动执行对应的getter方法并返回结果,而不是给你一个可调用对象。- 混淆了“方法引用”和“方法执行”:如果
some_method是实例方法,直接写SomeClass.some_method得到的是未绑定方法,但如果它依赖实例参数,可能你在传递流程中不小心触发了执行(不过你这里没加括号,大概率是第一种情况)。
解决方案
根据不同场景,给你几个实用的解决办法:
场景1:some_method是@property属性
用lambda包装延迟执行,这样只有在SomeFunction内部调用传入的参数时,才会触发属性的求值:
# 用lambda包裹,延迟获取属性值 some_variable = SomeFunction(lambda: SomeClass(expr_value, status_value).some_method, return_status=True)
如果你想直接传递属性对应的原始方法,可以用fget属性获取:
# 获取property对应的原始get方法 some_variable = SomeFunction(SomeClass.some_method.fget, return_status=True)
场景2:传递实例方法的引用(未创建实例)
如果你还没创建SomeClass的实例,想把方法和实例创建逻辑一起传递,可以用lambda闭包,或者传递类+方法名:
# 用lambda闭包,在需要时创建实例并调用方法 some_variable = SomeFunction(lambda: SomeClass(expr_value, status_value).some_method(), return_status=True) # 或者传递类和方法名,在SomeFunction内部处理 some_variable = SomeFunction((SomeClass, 'some_method'), return_status=True) # 对应的SomeFunction可以这样写: def SomeFunction(callable_info, return_status): cls, method_name = callable_info instance = cls(expr_value, return_status) method = getattr(instance, method_name) result = method() # 此时才会执行方法
场景3:传递带参数的方法引用
如果some_method需要额外参数,用functools.partial绑定参数,避免提前执行:
from functools import partial # 先创建实例 instance = SomeClass(expr_value, status_value) # 绑定方法和参数,得到一个可调用对象 bound_method = partial(instance.some_method, arg1, arg2) # 传递这个绑定后的方法 some_variable = SomeFunction(bound_method, return_status=True)
内容的提问来源于stack exchange,提问作者Vishal K Nair
相关产品推荐
相关产品推荐

