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.Int
和 declare.Float
是标准类型的预定义声明(还有 Bool
、Str
和 Bytes
)。您还可以通过导入 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 的响应式属性。
这个库提取了一些核心功能,使它们在没有其他依赖项的情况下也能工作。
它与数据类、traitlets、Pydantic、attrs 和其他类似项目有一些重叠。但 Declare 并不打算取代这些项目,这些项目提供了更多功能。实际上,您可以将声明的属性添加到这些其他库创建的类对象中。
如何?
一言以蔽之:"描述符"。Python 的描述符协议已经存在很长时间了,但我认为它仍然是一个未充分利用的功能。
谁?
谢谢!
非常感谢 Chris Cardillo,他非常友好地让我在 Pypi 上使用 declare
名称。
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。