在Python中记住静态属性

Memoizing static properties in Python

本问题已经有最佳答案,请猛点这里访问。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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的实例:

1
2
3
4
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时我才知道它的名称。


建议的可能副本已接近。classmethod装饰器的工作原理如该答案所述:

1
2
3
4
5
class classproperty(object):
    def __init__(self, getter):
        self.getter = getter
    def __get__(self, instance, owner):
        return self.getter(owner)

但是不需要定义类外的任何内容,因此:

1
2
3
4
5
6
7
8
9
class OftenUsedClass(object):

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

工作良好。