跳转到主要内容

Declare属性

项目描述

是什么?

Declare是添加Python类属性的一种语法糖,支持验证和监视属性变化。

尽管在许多情况下不需要编写类型注解,Declare与MyPy等类型检查器配合良好。

示例

让我们看一个简单的例子。以下代码创建了一个表示颜色的类,具有红色、绿色、蓝色属性,以及一个alpha(透明度)组件

import declare


class Color:
    """A color object with RGB, and alpha components."""

    red = declare.Int(0)
    green = declare.Int(0)
    blue = declare.Int(0)
    alpha = declare.Float(1.0)

如果你构造一个Color实例,它将具有这四个属性。

也许令人惊讶的是,这些属性是有类型的--没有显式的类型注解。Mypy和其他类型检查器将理解Color实例有三个int属性,以及额外的float属性用于alpha。

验证

到目前为止,与传统属性相比,好处不大,但Declare提供了一种方便的添加验证的方式。

以下代码扩展了Color类,为所有四个属性添加了验证

import declare


class Color:
    """A color object with RGB, and alpha components."""

    red = declare.Int(0)
    green = declare.Int(0)
    blue = declare.Int(0)
    alpha = declare.Float(1.0)

    @red.validate
    @green.validate
    @blue.validate
    def _validate_component(self, component: int) -> int:
        """Restrict RGB to 0 -> 255."""
        return max(0, min(255, component))

    @alpha.validate
    def _validate_alpha(self, alpha: float) -> float:
        return max(0.0, min(1.0, alpha))

如果你尝试将一个值赋给属性,而这个值超出了预期范围,那么这个值将被限制在上下范围内。换句话说,将my_color.red=300实际上会将red属性设置为255

在验证器中,您可以执行任何操作来更改存储的值,或者如果值无效,可能抛出一个异常。

监控

除了验证属性外,您还可以监控属性的变化。当一个属性具有监控方法时,当值发生变化时将调用该方法。该方法将接收原始值和即将设置的新的值。

以下是一个扩展了监控方法的颜色类

import declare


class Color:
    """A color object with RGB, and alpha components."""

    red = declare.Int(0)
    green = declare.Int(0)
    blue = declare.Int(0)
    alpha = declare.Float(1.0)

    @red.validate
    @green.validate
    @blue.validate
    def _validate_component(self, component: int) -> int:
        """Restrict RGB to 0 -> 255."""
        return max(0, min(255, component))

    @alpha.validate
    def _validate_alpha(self, alpha: float) -> float:
        return max(0.0, min(1.0, alpha))

    @alpha.watch
    def _watch_alpha(self, old_alpha: float, alpha: float) -> None:
        print(f"alpha changed from {old_alpha} to {alpha}!")

添加 @alpha.watch 装饰器会导致在将任何值赋给 alpha 属性时调用 _watch_alpha 方法。

声明类型

在上面的代码中,declare.Intdeclare.Float 是标准类型的预定义声明(还有 BoolStrBytes)。您还可以通过导入 Declare 来声明自定义类型。

让我们添加一个包含名称和颜色列表的 Palette

import declare
from declare import Declare


class Color:
    """A color object with RGB, and alpha components."""

    red = declare.Int(0)
    green = declare.Int(0)
    blue = declare.Int(0)
    alpha = declare.Float(1.0)

    @red.validate
    @green.validate
    @blue.validate
    def _validate_component(self, component: int) -> int:
        """Restrict RGB to 0 -> 255."""
        return max(0, min(255, component))

    @alpha.validate
    def _validate_alpha(self, alpha: float) -> float:
        return max(0.0, min(1.0, alpha))

    @alpha.watch
    def _watch_alpha(self, old_alpha: float, alpha: float) -> None:
        print(f"alpha changed from {old_alpha} to {alpha}!")


class Palette:
    """A container of colors."""
    name = declare.Str("")
    colors = Declare[list[Color]]([])

colors 属性是通过此调用创建的:Declare[list[Color]]([]),它创建一个颜色列表,默认为空列表。

让我们稍作分解

  • Declare 是创建属性的描述符。
  • Declare[list[Color]] 告诉类型检查器您正在声明一个颜色对象的列表。
  • Declare[list[Color]]([]) 设置默认为空列表。请注意,这不会受到经典 Python 默认可变参数问题的困扰。每次构建 Palette 时,您都会得到一个新实例。

安装

通过 pip 或您喜欢的包管理器进行安装。

pip install declare

为什么?

Textual 使用类似的方法来声明 响应式属性,这是一个有用的通用编程概念。遗憾的是,没有 Textual 作为运行时,将无法在另一个项目中使用 Textual 的响应式属性。

这个库提取了一些核心功能,使它们在没有其他依赖项的情况下也能工作。

它与数据类、traitletsPydanticattrs 和其他类似项目有一些重叠。但 Declare 并不打算取代这些项目,这些项目提供了更多功能。实际上,您可以将声明的属性添加到这些其他库创建的类对象中。

如何?

一言以蔽之:"描述符"。Python 的描述符协议已经存在很长时间了,但我认为它仍然是一个未充分利用的功能。

谁?

谢谢!

非常感谢 Chris Cardillo,他非常友好地让我在 Pypi 上使用 declare 名称。

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。

源分布

declare-1.0.1.tar.gz (5.2 kB 查看哈希值)

上传时间:

构建分布

declare-1.0.1-py3-none-any.whl (5.9 kB 查看哈希值)

上传于 Python 3

由以下支持