【问题标题】:Use `super` function into `partialmethod`在 `partialmethod` 中使用 `super` 函数
【发布时间】:2022-06-11 19:51:50
【问题描述】:

我正在尝试使用神奇的 python partialmethod functool。但是这个部分方法必须引用我父类中的一个函数。 考虑下面的测试代码:

from functools import partialmethod

class MyResource:
    @staticmethod
    def load_resource(id):
        print(f"Loding 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(_get_resource, MyResource)
   def run(self):
       obj1 = _get_my_resource(12345)
       obj2 = _get_my_resource(12345)
       return obj1, obj2

MyClass().run()

当我尝试运行此代码时,我在_get_my_resource = partialmethod(_get_resource, MyResource) 上收到一条错误消息NameError: name '_get_resource' is not defined

我尝试使用partialmethod(self._get_resource, MyResource)partialmethod(super()._get_resource, MyResource),但它不起作用。

我找到了一种解决方法,将_get_resource 函数重新声明为MyClass,但这个解决方案对我来说似乎很丑:

class MyClass(CachedDataMixin):
    def _wrapped_get_resource(self, source_cls, id):
        return super()._get_resource(source_cls, id)
   _get_my_resource = partialmethod(_wrapped_get_resource, MyResource)
   ...

有没有人有一个很好的解决方案来不写我丑陋的解决方法? 非常感谢您的帮助

【问题讨论】:

    标签: python


    【解决方案1】:

    这里有几件事:

    1. 您不能在类属性中引用CachedDataMixin._get_resource,因为它没有在类本身中定义。 MyClass 的实例会拥有它,但类对象与实例对象不同。
    2. 您不能使用 self 出于同样的原因:它仅在方法中定义,并引用实例对象。
    3. super() 在从方法调用时动态工作(并使用实例),因此在类 attribute 中使用它也不走运。
    4. 你可以在这里硬编码类名:
      _get_my_resource = partialmethod(CachedDataMixin._get_resource, MyResource)
      
      我个人会选择更明确的选择:
      def _get_my_resource(self, id_):
          return super()._get_resource(MyResource, id_)
      
    5. 然后,经过如下几个修复:
      # you forgot to call a method using `self`
      obj1 = self._get_my_resource(12345)
      
      class MyResource:
          # otherwise you can't do `MyResource(12345)`
          def __init__(self, id_):
              self.id = id_
      

    它终于成功了(“加载资源”只有一次,没有错误)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 2023-04-09
      • 2018-01-10
      • 1970-01-01
      • 2013-02-18
      • 2012-05-17
      相关资源
      最近更新 更多