def lazy_property(func):
    """惰性属性修饰器。

    如我们可以定义下面一个 `Circle` 的类，定义其中
    计算面积的属性为惰性属性

    .. code-block:: python

        @dataclass
        class Circle:
            x: float
            y: float
            r: float

            @lazy_property
            def area(self):
                print("computing")
                return 3.14 * r * r

    调用时结果如下，可以发现仅第一次发生了计算：

    >>> cir = Circle(0, 1, 1)
    >>> cir.area
    computing
    3.14
    >>> cir.area
    3.14
    """
    attr_name = "_lazy_" + func.__name__

    @property
    def _lazy_property(self):
        if not hasattr(self, attr_name):
            setattr(self, attr_name, func(self))
        return getattr(self, attr_name)

    return _lazy_property