Python使用Traits库实现对象属性

 更新时间:2023年11月04日 15:41:34   投稿:yin  
Python作为一种动态编程语言,它的变量没有类型,这种灵活性给快速开发带来很多便利,不过它也不是没有缺点,Traits库的一个很重要的目的就是为了解决这些缺点所带来的问题,trait为Python对象的属性增加了类型定义的功能

Python作为一种动态编程语言,它的变量没有类型,这种灵活性给快速开发带来很多便利,不过它也不是没有缺点。Traits库的一个很重要的目的就是为了解决这些缺点所带来的问题。

背景

Traits库最初是为了开发Chaco(一个2D绘图库)而设计的,绘图库中有很多绘图用的对象,每个对象都有很多例如线型、颜色、字体之类的属性。为了方便用户使用,每个属性可以允许多种形式的值。例如,颜色属性可以是'red'、0xff0000、(255, 0, 0)

也就是说可以用字符串、整数、组元等类型的值表达颜色,这样的需求初看起来用Python的无类型变量是一个很好的选择,因为我们可以把各种各样的值赋值给颜色属性。但是颜色属性虽然可以接受多样的值,却不是能接受所有的值,比如"abc"、0.5等等就不能很好地表示颜色。而且虽然为了方便用户使用,对外的接口可以接受各种各样形式的值,但是在内部必须有一个统一的表达方式来简化程序的实现。

用Trait属性可以很好地解决这样的问题:

  • 它可以接受能表示颜色的各种类型的值
  • 当给它赋值为不能表达颜色的值时,它能够立即捕捉到错误,并且提供一个有用的错误报告,告诉用户它能够接受什么样的值
  • 它提供一个内部的标准的颜色表达方式

让我们来看一下使用traits属性表示颜色的例子:

from enthought.traits.api import HasTraits, Color

class Circle(HasTraits):
    color = Color

这个程序从enthought.traits.api中导入我们需要使用的两个对象: HasTraits和Color。所有拥有trait属性的类都需要从HasTraits继承。由于Python的多继承特性,我们很容易将现有的类改为支持trait属性。Color是一个TraitFactory对象,我们在Circle类的定义中用它来声明一个color属性。

Traits是什么

trait为Python对象的属性增加了类型定义的功能,此外还提供了如下的额外功能:

  • 初始化:每个trait属性都定义有自己的缺省值,这个缺省值用来初始化属性
  • 验证:基于trait的属性都有明确的类型定义,只有满足定义的值才能赋值给属性
  • 委托:trait属性的值可以委托给其他对象的属性
  • 监听:trait属性的值的改变可以触发指定的函数的运行
  • 可视化:拥有trait属性的对象可以很方便地提供一个用户界面交互式地改变trait属性的值

下面这个简单的例子展示了trait所提供的这五项能力:

from enthought.traits.api import Delegate, HasTraits, Instance, Int, Str

class Parent ( HasTraits ):
    # 初始化: last_name被初始化为'Zhang'
    last_name = Str( 'Zhang' )

class Child ( HasTraits ):
    age = Int

    # 验证: father属性的值必须是Parent类的实例
    father = Instance( Parent )

    # 委托: Child的实例的last_name属性委托给其father属性的last_name
    last_name = Delegate( 'father' )

    # 监听: 当age属性的值被修改时,下面的函数将被运行
    def _age_changed ( self, old, new ):
        print 'Age changed from %s to %s ' % ( old, new )

下面用这两个类创建立两个实例:

>>> p = Parent()
>>> c = Child()

由于没有设置c的father属性,因此无法获得它的last_name属性:

>>> c.last_name
Traceback (most recent call last):
AttributeError: 'NoneType' object has no attribute 'last_name'

设置father属性之后,我们就可以得到c的last_name了:

>>> c.father = p
>>> c.last_name
'Zhang'

设置c的age属性将触发_age_changed方法的执行:

>>> c.age = 4
Age changed from 0 to 4

调用configure_traits:

>>> c.configure_traits()
True

弹出一个如下的对话框,用户可以通过它修改c的trait属性,

为Child类自动生成的属性修改对话框

可以看到属性按照其英文名排序,垂直排为一列。由于father属性是Parent类的实例,所以它给我们一个按钮,点此按钮出现下面的设置father对象的tratis属性的对话框

点击Child对话框中的Father按钮之后,弹出编辑father属性的对话框

在上面这个对话框中修改father的Last name,可以看到child的Last name属性也随之发生变化。

我们可以调用print_traits方法输出所有的trait属性与其值:

>>> c.print_traits()
age:       4
father:    <__main__.Parent object at 0x13B49120>
last_name: u'Zhang'

调用get方法获得一个描述对象所有trait属性的dict:

>>> c.get()
{'age': 4, 'last_name': u'Zhang', 'father': <__main__.Parent object at 0x13B49120>}

此外还可以调用set方法设置trait属性的值,set方法可以同时配置多个trait的属性:

>>> c.set(age = 6)
Age changed from 4 to 6
<__main__.Child object at 0x13B494B0>

动态添加Trait属性

前面介绍的方法都是在类的定义中声明Trait属性,在类的实例中使用Trait属性。由于Python是动态语言,因此Traits库也提供了为某个特定的实例添加Trait属性的方法。

下面的例子,直接产生HasTraits类的一个实例a, 然后调用其add_trait方法动态地为a添加一个名为x的Trait属性,其类型为Float,初始值为3.0。

>>> from enthought.traits.api import *
>>> a = HasTraits()
>>> a.add_trait("x", Float(3.0))
>>> a.x
3.0

接下来再创建一个HasTraits类的实例b,用add_trait方法为b添加一个属性a,指定其类型为HasTraits类的实例。然后把实例a赋值给实例b的属性a:b.a。

>>> b = HasTraits()
>>> b.add_trait("a", Instance(HasTraits))
>>> b.a = a

然后为实例b添加一个类型为Delegate(代理)的属性y,它是b的属性a所表示的实例的属性x的代理,即b.y是b.a.x的代理。注意我们在用Delegate声明代理时,第一个参数b的一个属性名"a",第二个参数是是此属性的属性名"x",modify=True表示可以通过b.y修改b.a.x的值。我们看到当将b.y的值改为10的时候,a.x的值也同时改变了。

>>> b.add_trait("y", Delegate("a", "x", modify=True))
>>> b.y
3.0
>>> b.y = 10
>>> a.x
10.0

Traits 的使用场景

Traits 的使用场景非常广泛,以下是一些常见的应用场景:

1. 插件系统

Traits 可以用于创建插件系统,使得我们可以为应用程序添加新的功能或模块,而无需修改现有的代码。通过定义一系列的 Traits 类,我们可以轻松地将这些模块组合起来,实现动态的功能扩展。

2. 用户界面开发

Traits 提供了一种简单而强大的方式来创建用户界面。我们可以定义各种用户界面元素的 Traits,然后将它们组合在一起以构建复杂的界面。Traits 还支持属性验证和事件通知,使得我们可以轻松地处理用户输入和交互。

3. 数据分析和科学计算

Traits 提供了一种方便的方式来处理和分析数据。我们可以定义各种数据结构的 Traits,然后使用这些 Traits 来创建和操作数据。Traits 还支持属性验证和默认值,使得数据处理更加健壮和可靠。

 总结

Traits 是一个在 Python 中用于实现对象属性的库。Traits 可以帮助我们创建可复用、健壮和可扩展的代码。在软件开发中,Traits 是一种用于描述对象属性的概念。一个 Trait 是一个可重用的代码块,它定义了一组属性和方法,这些属性和方法可以被其他对象继承和使用。Traits 可以用于创建可插拔组件、增加代码的可读性和可维护性,以及提供代码的灵活性和复用性。

相关文章

  • python一行代码就能实现数据分析的pandas-profiling库

    python一行代码就能实现数据分析的pandas-profiling库

    这篇文章主要为大家介绍了python一行代码就能实现数据分析的pandas-profiling库,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • python表格存取的方法

    python表格存取的方法

    这篇文章主要为大家详细介绍了python表格存取的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • python下载安装requests库的简单步骤

    python下载安装requests库的简单步骤

    这篇文章主要给大家介绍了关于python下载安装requests库的简单步骤,使用Python的requests库下载文件是一种常见的操作,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • flask框架单元测试原理与用法实例分析

    flask框架单元测试原理与用法实例分析

    这篇文章主要介绍了flask框架单元测试原理与用法,结合实例形式较为详细的分析了单元测试的概念、原理及基本用法,需要的朋友可以参考下
    2019-07-07
  • Pandas数据分析的一些常用小技巧

    Pandas数据分析的一些常用小技巧

    这篇文章主要介绍了Pandas数据分析的一些常用小技巧,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • Python游戏开发之精灵和精灵组

    Python游戏开发之精灵和精灵组

    python作为当前非常受欢迎的编程语言,很大一部分原因是拥有丰富的库,这篇文章主要给大家介绍了关于Python游戏开发之精灵和精灵组的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • 学习和使用python的13个理由

    学习和使用python的13个理由

    在本篇文章里小编给大家整理了关于学习和使用python的13个理由以及相关知识点,需要的朋友们参考下。
    2019-07-07
  • Django单元测试的具体使用

    Django单元测试的具体使用

    Django提供了一套强大的测试工具来帮助开发者编写和运行单元测试,本文就来介绍一下Django中的单元测试,包括测试原理、编写测试用例和运行测试,感兴趣的可以了解一下
    2023-11-11
  • python 将Excel转Word的示例

    python 将Excel转Word的示例

    这篇文章主要介绍了python 将Excel转Word的示例,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下
    2021-03-03
  • Python3.遍历某文件夹提取特定文件名的实例

    Python3.遍历某文件夹提取特定文件名的实例

    下面小编就为大家分享一篇Python3.遍历某文件夹提取特定文件名的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-04-04

最新评论