Python中如何在partialmethod中正确引用父类方法
问题原因
这个NameError是Python类定义阶段的命名空间规则导致的:
- 类体代码执行时,当前类的对象还没创建完成,从父类继承的方法不会进入类体的临时局部命名空间,直接写裸名
_get_resource自然找不到定义 - 类定义阶段既没有生成实例(不存在
self变量),也没有完整的类继承链(MRO)上下文,所以self._get_resource、super()._get_resource两种写法都跑不通——这两个关键字只有在实例方法被调用的阶段才会生效。
另外你给的测试代码还有个小bug:run方法里直接写_get_my_resource(12345)也会报错,这个partialmethod是绑定在类上的属性,必须通过实例调用,也就是要写成self._get_my_resource(12345)。
最简实现
完全不需要写冗余的包装方法,定义partialmethod时直接引用已经创建完成的父类方法就行,可运行代码如下:
from functools import partialmethod class MyResource: @staticmethod def load_resource(id): print(f"Loading a new resource ! {id}") return MyResource(id) class CachedDataMixin: _cache = {} def _get_resource(self, source_cls, id): if source_cls not in self._cache or id not in self._cache[source_cls]: resource = source_cls.load_resource(id) self._cache.setdefault(source_cls, {})[id] = resource return self._cache[source_cls][id] class MyClass(CachedDataMixin): # 直接引用父类已定义的方法,无需额外包装 _get_my_resource = partialmethod(CachedDataMixin._get_resource, MyResource) def run(self): obj1 = self._get_my_resource(12345) obj2 = self._get_my_resource(12345) return obj1, obj2 MyClass().run()
逻辑说明
- 代码执行到
_get_my_resource赋值这一行时,父类CachedDataMixin已经完成类创建流程,它的_get_resource方法作为类属性可以直接访问 partialmethod本身就会处理实例绑定逻辑:通过子类实例调用self._get_my_resource()时,会自动把当前实例作为第一个self参数传入原方法,和普通继承方法的调用行为完全一致- 这种写法和你之前写包装层的逻辑完全等价,但是少了一层无意义的函数嵌套。
如果你的场景需要让这个绑定方法动态遵循MRO(比如后续子类可能重写_get_resource,希望partialmethod自动调用重写后的版本),可以配合__init_subclass__钩子做动态绑定,绝大多数业务场景下上面的写法已经完全满足需求。
内容的提问来源于stack exchange,提问作者Renaud Michotte
相关产品推荐
相关产品推荐

