【问题标题】:Memoizing static properties in Python [duplicate]在 Python 中记忆静态属性 [重复]
【发布时间】:2016-09-27 14:07:12
【问题描述】:

我有两个类,其中一个的设置成本很高,但可重用,另一个在我的应用程序中有很多实例,但可以重用昂贵类的实例。这更容易通过例子来解释:

class SomeExpensiveToSetUpClass(object):
    def __init__(self):
        print("Expensive to set up class initialized")
        self.whatever = "Hello"

    def do_the_thing(self):
        print(self.whatever)

class OftenUsedClass(object):

    @staticmethod
    @property
    def expensive_property():
        try:
            return OftenUsedClass._expensive_property
        except AttributeError:
            OftenUsedClass._expensive_property = SomeExpensiveToSetUpClass()
            return OftenUsedClass._expensive_property

    # I know I could hide the static property in an instance property:
    @property
    def expensive_property2(self):
        try:
            return OftenUsedClass._expensive_property
        except AttributeError:
            OftenUsedClass._expensive_property = SomeExpensiveToSetUpClass()
            return OftenUsedClass._expensive_property
    #
    # And then:
    #
    # ouc = OftenUsedClass()
    # ouc.expensive_property2.do_the_thing()
    # ouc.expensive_property2.do_the_thing()
    # ouc.expensive_property2.do_the_thing()
    #
    # but that feels misleading

if __name__ == '__main__':
    OftenUsedClass.expensive_property.do_the_thing()
    OftenUsedClass.expensive_property.do_the_thing()
    OftenUsedClass.expensive_property.do_the_thing()

如您所见,我希望我会使用 @staticmethod@property 在第一次使用该属性时基本上记住该属性,但没有骰子——我得到了一个 property 的实例改为返回:

Traceback (most recent call last):
  File "memo.py", line 39, in <module>
    OftenUsedClass.expensive_property.do_the_thing()
AttributeError: 'property' object has no attribute 'do_the_thing'

我发现了几种用于记忆装饰器的模式,但没有找到用于静态属性的模式。我错过了什么吗?或者我应该使用其他模式吗?

编辑:

我的问题过于简单化了:我应该在配置文件中包含 SomeExpensiveToSetUpClass 类实现的名称,所以直到第一次实例化 OftenUsedClass 时我才知道它的名称。

【问题讨论】:

  • 我不确定我是否正确地遵循了你,因为你的例子相当复杂,但你不能将 SomeExpensiveToSetUpClass() 转换为单例(因为该类只有一个实例),然后调度所有需要在“OftenUsedClass”中调用该单例吗?
  • @Rogalski - 谢谢!我添加了一个说明,说明为什么单例是不可能的。对不起,我第一次不够清楚。
  • 也许这个describing a lazily calculated class attribute 会有用。你可以在这里使用@class_reify def expensive_property(): return SomeExpensiveToSetUpClass()
  • 对不起,那是def expensive_property(cls)

标签: python python-3.x memoization


【解决方案1】:

建议的possible duplicate 已接近。 classmethod 装饰器的工作方式如该答案中所述:

class classproperty(object):
    def __init__(self, getter):
        self.getter = getter
    def __get__(self, instance, owner):
        return self.getter(owner)

但是没有必要在类之外定义任何东西,所以:

class OftenUsedClass(object):

    @classproperty
    def expensive_property3(cls):
        try:
            return cls._expensive_property
        except AttributeError:
            cls._expensive_property = SomeExpensiveToSetUpClass()
            return cls._expensive_property

工作正常。

【讨论】:

  • 接近是什么意思?这正是that answer 的详细信息,x = 4 是用户的具体情况。
  • 我很抱歉:在那个答案中,我不明白为什么 Foo.x 还不够。也许我错过了什么?
  • 我读到这个例子暗示我必须在expensive_property 方法之外定义_expensive_property
  • 即属性代码中except AttributeError的点,如果尚未定义,则在第一次尝试使用时定义。
  • 正是...这就是它们的不同之处。
猜你喜欢
  • 2020-05-23
  • 1970-01-01
  • 2014-12-07
  • 1970-01-01
  • 2012-11-22
  • 1970-01-01
  • 2015-08-13
  • 2013-08-17
  • 1970-01-01
相关资源
最近更新 更多