Python 实现数据模型的类型约束 问题
你想定义某些在属性赋值上面有限制的数据结构。
Python 实现数据模型的类型约束 解决方案
在这个问题中,你需要在对某些实例属性赋值时进行检查。 所以你要自定义属性赋值函数,这种情况下最好使用描述器。
下面的代码使用描述器实现了一个系统类型和赋值验证框架:
这些类就是你要创建的数据模型或类型系统的基础构建模块。 下面就是我们实际定义的各种不同的数据类型:
然后使用这些自定义数据类型,我们定义一个类:
然后测试这个类的属性赋值约束,可发现对某些属性的赋值违法了约束是不合法的:
还有一些技术可以简化上面的代码,其中一种是使用类装饰器:
另外一种方式是使用元类:
Python 实现数据模型的类型约束 讨论
本节使用了很多高级技术,包括描述器、混入类、super()
的使用、类装饰器和元类。 不可能在这里一一详细展开来讲,但是可以在8.9、8.18、9.19小节找到更多例子。 但是,我在这里还是要提一下几个需要注意的点。
首先,在 Descriptor
基类中你会看到有个 __set__()
方法,却没有相应的 __get__()
方法。 如果一个描述仅仅是从底层实例字典中获取某个属性值的话,那么没必要去定义 __get__()
方法。
所有描述器类都是基于混入类来实现的。比如 Unsigned
和 MaxSized
要跟其他继承自 Typed
类混入。 这里利用多继承来实现相应的功能。
混入类的一个比较难理解的地方是,调用 super()
函数时,你并不知道究竟要调用哪个具体类。 你需要跟其他类结合后才能正确的使用,也就是必须合作才能产生效果。
使用类装饰器和元类通常可以简化代码。上面两个例子中你会发现你只需要输入一次属性名即可了。
所有方法中,类装饰器方案应该是最灵活和最高明的。 首先,它并不依赖任何其他新的技术,比如元类。其次,装饰器可以很容易的添加或删除。
最后,装饰器还能作为混入类的替代技术来实现同样的效果;
这种方式定义的类跟之前的效果一样,而且执行速度会更快。 设置一个简单的类型属性的值,装饰器方式要比之前的混入类的方式几乎快100%。