Python 中计算静态属性

问题描述 投票:0回答:5

是否有可能在一个类上拥有一个静态属性,该属性将被一次性计算。我们的想法是能够像这样做到:

class Foo:
    static_prop = Foo.one_off_static_method()

    @staticmethod
    def one_off_static_method():
        return 'bar'

我也想过使用

__new__

Class Foo:
    def __new__(cls):
         cls.static_prop = ... do everything here

但不确定这意味着什么。

python static-methods
5个回答
6
投票

如果您希望在类定义时计算它,请参阅 chepner 的答案 - 尽管我建议只使用模块级函数。

如果您希望对每个实例进行延迟评估,那么您可能会对

functools.cached_property
感兴趣。

>>> from random import random
>>> from functools import cached_property
>>> class Foo(object):
...     @cached_property
...     def one_off_thing(self):
...         print("computing...")
...         return random()
...     
>>> foo = Foo()
>>> foo.one_off_thing
computing...
0.5804382038855782
>>> foo.one_off_thing
0.5804382038855782

注意: stdlib

functools.cached_property
需要 Python 3.8+,对于 Python < 3.8 you can
pip install cached_property


3
投票

给你,我为你做了一个小描述符:-)

访问属性时,它将被计算并缓存。

class CachedStaticProperty:
    """Works like @property and @staticmethod combined"""

    def __init__(self, func):
        self.func = func

    def __get__(self, inst, owner):
        result = self.func()
        setattr(owner, self.func.__name__, result)
        return result

它的工作方式相当简单:

  1. 使用装饰器语法后,我在内部保存该函数。
  2. 访问时,我调用该函数并将该值设置为与原始函数同名的类值。

仅此而已。简单高效。


1
投票

在实际创建类之前,

one_off_static_method
只是一个常规函数。在尝试调用它之前需要定义它,因为您想在执行
class
语句时调用它。一旦你完成了它,你可以简单地删除它。

class Foo:
    def _one_off_static_method():
        return 'bar'

    static_prop = _one_off_static_method()
    del _one_off_static_method

1
投票

从 Python 3.8 开始,Python 内置/核心

cached_property
库中将包含一个
functools
装饰器。

https://docs.python.org/dev/library/functools.html?highlight=s#functools.cached_property

本网站其他问题也有类似的答案。一些亮点是人们可以做的

@property
@functools.lru_cache(1)

(都是 Python 内置函数)以获得类似的效果。而且一些 Web 服务器库(例如 Flask 或 Werkzeug)已经包含了自己的

cached_property
装饰器实现。

当然还有其他方法(如该问题的其他答案和其他问题的答案中提到的)可以创建自己的自定义缓存属性装饰器。

python:属性字段是否会自动缓存?
有没有一个装饰器可以简单地缓存函数返回值?


0
投票

你可以使用这个模式

import functools

class DataSet:

    def __init__(self, sequence_of_numbers):
        self._data = tuple(sequence_of_numbers)

    @classmethod
    @property # equivalent to "lambda f: property(fget=f)"
    @functools.cache
    def thing5(cls):
        print("executing thing5")
        return 25

print(DataSet.thing5)
print(DataSet.thing5)

产生这个输出

executing thing5
25
25
© www.soinside.com 2019 - 2024. All rights reserved.