Python中setattr绑定函数后__name__属性不符问题咨询
问题分析与解决方法
我来帮你理清楚这个问题哈~
为什么f.con.__name__会返回condition?
当你用setattr(self, accessor, self.condition)把condition方法赋值给实例的con/don属性时,本质上只是把同一个函数对象的引用绑定到了不同的实例属性上。函数对象的__name__属性是在它被定义的时候就固定下来的,存储的是它定义时的名称(也就是condition),并不会因为这个函数被赋值给不同的变量或属性就自动改变。
打个比方:就像你给一个叫「张三」的朋友起了个外号「阿三」,但朋友本身的本名还是「张三」,不会因为外号而改变——这里的condition函数就是「张三」,con/don只是它的“外号”,函数自身的__name__自然还是原来的名字。
解决方法
下面给你两种可行的解决思路,你可以根据自己的需求选择:
方法1:用functools.wraps修改函数元数据
functools模块里的wraps装饰器可以帮我们修改函数的元数据(包括__name__),让它“伪装”成我们指定的名称。如果你的condition方法需要用到当前的属性名(比如查询self.accessor_column),还可以结合partial来传递参数:
import functools class Filter: def __init__(self, column=['poi_id', 'tp.event'], access=['con', 'don']): self.column = column self.access = access self.accessor_column = dict(zip(self.access, self.column)) self.set_conditions() def condition(self, accessor_name, name): # 这里可以直接用传入的accessor_name查询对应的列 target_col = self.accessor_column.get(accessor_name) print(f"当前使用列: {target_col}") return name def set_conditions(self): for poi_column, accessor in zip(self.column, self.access): # 用partial绑定accessor参数,同时修改__name__ wrapped_func = functools.partial(self.condition, accessor) wrapped_func.__name__ = accessor setattr(self, accessor, wrapped_func)
方法2:动态创建新的函数对象
如果你想更彻底一点,可以直接创建新的函数对象,复用原函数的代码逻辑,同时指定新的名称:
import types class Filter: def __init__(self, column=['poi_id', 'tp.event'], access=['con', 'don']): self.column = column self.access = access self.accessor_column = dict(zip(self.access, self.column)) self.set_conditions() def condition(self, name): return name def set_conditions(self): for poi_column, accessor in zip(self.column, self.access): # 创建新的函数对象,指定新的名称 new_func = types.FunctionType( self.condition.__code__, self.condition.__globals__, name=accessor, argdefs=self.condition.__defaults__, closure=self.condition.__closure__ ) # 将新函数绑定到当前实例 bound_func = new_func.__get__(self, Filter) setattr(self, accessor, bound_func)
验证效果
运行修改后的代码,就能得到你想要的结果:
>>> f = Filter() >>> print(f.con('linux')) linux >>> print(f.con.__name__) con >>> print(f.don.__name__) don
内容的提问来源于stack exchange,提问作者nosahama
相关产品推荐
相关产品推荐

