Python使用Traits庫實(shí)現(xiàn)對(duì)象屬性
Python作為一種動(dòng)態(tài)編程語言,它的變量沒有類型,這種靈活性給快速開發(fā)帶來很多便利,不過它也不是沒有缺點(diǎn)。Traits庫的一個(gè)很重要的目的就是為了解決這些缺點(diǎn)所帶來的問題。
背景
Traits庫最初是為了開發(fā)Chaco(一個(gè)2D繪圖庫)而設(shè)計(jì)的,繪圖庫中有很多繪圖用的對(duì)象,每個(gè)對(duì)象都有很多例如線型、顏色、字體之類的屬性。為了方便用戶使用,每個(gè)屬性可以允許多種形式的值。例如,顏色屬性可以是'red'、0xff0000、(255, 0, 0)
也就是說可以用字符串、整數(shù)、組元等類型的值表達(dá)顏色,這樣的需求初看起來用Python的無類型變量是一個(gè)很好的選擇,因?yàn)槲覀兛梢园迅鞣N各樣的值賦值給顏色屬性。但是顏色屬性雖然可以接受多樣的值,卻不是能接受所有的值,比如"abc"、0.5等等就不能很好地表示顏色。而且雖然為了方便用戶使用,對(duì)外的接口可以接受各種各樣形式的值,但是在內(nèi)部必須有一個(gè)統(tǒng)一的表達(dá)方式來簡(jiǎn)化程序的實(shí)現(xiàn)。
用Trait屬性可以很好地解決這樣的問題:
- 它可以接受能表示顏色的各種類型的值
- 當(dāng)給它賦值為不能表達(dá)顏色的值時(shí),它能夠立即捕捉到錯(cuò)誤,并且提供一個(gè)有用的錯(cuò)誤報(bào)告,告訴用戶它能夠接受什么樣的值
- 它提供一個(gè)內(nèi)部的標(biāo)準(zhǔn)的顏色表達(dá)方式
讓我們來看一下使用traits屬性表示顏色的例子:
from enthought.traits.api import HasTraits, Color class Circle(HasTraits): color = Color
這個(gè)程序從enthought.traits.api中導(dǎo)入我們需要使用的兩個(gè)對(duì)象: HasTraits和Color。所有擁有trait屬性的類都需要從HasTraits繼承。由于Python的多繼承特性,我們很容易將現(xiàn)有的類改為支持trait屬性。Color是一個(gè)TraitFactory對(duì)象,我們?cè)贑ircle類的定義中用它來聲明一個(gè)color屬性。
Traits是什么
trait為Python對(duì)象的屬性增加了類型定義的功能,此外還提供了如下的額外功能:
- 初始化:每個(gè)trait屬性都定義有自己的缺省值,這個(gè)缺省值用來初始化屬性
- 驗(yàn)證:基于trait的屬性都有明確的類型定義,只有滿足定義的值才能賦值給屬性
- 委托:trait屬性的值可以委托給其他對(duì)象的屬性
- 監(jiān)聽:trait屬性的值的改變可以觸發(fā)指定的函數(shù)的運(yùn)行
- 可視化:擁有trait屬性的對(duì)象可以很方便地提供一個(gè)用戶界面交互式地改變trait屬性的值
下面這個(gè)簡(jiǎn)單的例子展示了trait所提供的這五項(xiàng)能力:
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 # 驗(yàn)證: father屬性的值必須是Parent類的實(shí)例 father = Instance( Parent ) # 委托: Child的實(shí)例的last_name屬性委托給其father屬性的last_name last_name = Delegate( 'father' ) # 監(jiān)聽: 當(dāng)age屬性的值被修改時(shí),下面的函數(shù)將被運(yùn)行 def _age_changed ( self, old, new ): print 'Age changed from %s to %s ' % ( old, new )
下面用這兩個(gè)類創(chuàng)建立兩個(gè)實(shí)例:
>>> p = Parent() >>> c = Child()
由于沒有設(shè)置c的father屬性,因此無法獲得它的last_name屬性:
>>> c.last_name Traceback (most recent call last): AttributeError: 'NoneType' object has no attribute 'last_name'
設(shè)置father屬性之后,我們就可以得到c的last_name了:
>>> c.father = p >>> c.last_name 'Zhang'
設(shè)置c的age屬性將觸發(fā)_age_changed方法的執(zhí)行:
>>> c.age = 4 Age changed from 0 to 4
調(diào)用configure_traits:
>>> c.configure_traits() True
彈出一個(gè)如下的對(duì)話框,用戶可以通過它修改c的trait屬性,
為Child類自動(dòng)生成的屬性修改對(duì)話框
可以看到屬性按照其英文名排序,垂直排為一列。由于father屬性是Parent類的實(shí)例,所以它給我們一個(gè)按鈕,點(diǎn)此按鈕出現(xiàn)下面的設(shè)置father對(duì)象的tratis屬性的對(duì)話框
點(diǎn)擊Child對(duì)話框中的Father按鈕之后,彈出編輯father屬性的對(duì)話框
在上面這個(gè)對(duì)話框中修改father的Last name,可以看到child的Last name屬性也隨之發(fā)生變化。
我們可以調(diào)用print_traits方法輸出所有的trait屬性與其值:
>>> c.print_traits() age: 4 father: <__main__.Parent object at 0x13B49120> last_name: u'Zhang'
調(diào)用get方法獲得一個(gè)描述對(duì)象所有trait屬性的dict:
>>> c.get() {'age': 4, 'last_name': u'Zhang', 'father': <__main__.Parent object at 0x13B49120>}
此外還可以調(diào)用set方法設(shè)置trait屬性的值,set方法可以同時(shí)配置多個(gè)trait的屬性:
>>> c.set(age = 6) Age changed from 4 to 6 <__main__.Child object at 0x13B494B0>
動(dòng)態(tài)添加Trait屬性
前面介紹的方法都是在類的定義中聲明Trait屬性,在類的實(shí)例中使用Trait屬性。由于Python是動(dòng)態(tài)語言,因此Traits庫也提供了為某個(gè)特定的實(shí)例添加Trait屬性的方法。
下面的例子,直接產(chǎn)生HasTraits類的一個(gè)實(shí)例a, 然后調(diào)用其add_trait方法動(dòng)態(tài)地為a添加一個(gè)名為x的Trait屬性,其類型為Float,初始值為3.0。
>>> from enthought.traits.api import * >>> a = HasTraits() >>> a.add_trait("x", Float(3.0)) >>> a.x 3.0
接下來再創(chuàng)建一個(gè)HasTraits類的實(shí)例b,用add_trait方法為b添加一個(gè)屬性a,指定其類型為HasTraits類的實(shí)例。然后把實(shí)例a賦值給實(shí)例b的屬性a:b.a。
>>> b = HasTraits() >>> b.add_trait("a", Instance(HasTraits)) >>> b.a = a
然后為實(shí)例b添加一個(gè)類型為Delegate(代理)的屬性y,它是b的屬性a所表示的實(shí)例的屬性x的代理,即b.y是b.a.x的代理。注意我們?cè)谟肈elegate聲明代理時(shí),第一個(gè)參數(shù)b的一個(gè)屬性名"a",第二個(gè)參數(shù)是是此屬性的屬性名"x",modify=True表示可以通過b.y修改b.a.x的值。我們看到當(dāng)將b.y的值改為10的時(shí)候,a.x的值也同時(shí)改變了。
>>> b.add_trait("y", Delegate("a", "x", modify=True)) >>> b.y 3.0 >>> b.y = 10 >>> a.x 10.0
Traits 的使用場(chǎng)景
Traits 的使用場(chǎng)景非常廣泛,以下是一些常見的應(yīng)用場(chǎng)景:
1. 插件系統(tǒng)
Traits 可以用于創(chuàng)建插件系統(tǒng),使得我們可以為應(yīng)用程序添加新的功能或模塊,而無需修改現(xiàn)有的代碼。通過定義一系列的 Traits 類,我們可以輕松地將這些模塊組合起來,實(shí)現(xiàn)動(dòng)態(tài)的功能擴(kuò)展。
2. 用戶界面開發(fā)
Traits 提供了一種簡(jiǎn)單而強(qiáng)大的方式來創(chuàng)建用戶界面。我們可以定義各種用戶界面元素的 Traits,然后將它們組合在一起以構(gòu)建復(fù)雜的界面。Traits 還支持屬性驗(yàn)證和事件通知,使得我們可以輕松地處理用戶輸入和交互。
3. 數(shù)據(jù)分析和科學(xué)計(jì)算
Traits 提供了一種方便的方式來處理和分析數(shù)據(jù)。我們可以定義各種數(shù)據(jù)結(jié)構(gòu)的 Traits,然后使用這些 Traits 來創(chuàng)建和操作數(shù)據(jù)。Traits 還支持屬性驗(yàn)證和默認(rèn)值,使得數(shù)據(jù)處理更加健壯和可靠。
總結(jié)
Traits 是一個(gè)在 Python 中用于實(shí)現(xiàn)對(duì)象屬性的庫。Traits 可以幫助我們創(chuàng)建可復(fù)用、健壯和可擴(kuò)展的代碼。在軟件開發(fā)中,Traits 是一種用于描述對(duì)象屬性的概念。一個(gè) Trait 是一個(gè)可重用的代碼塊,它定義了一組屬性和方法,這些屬性和方法可以被其他對(duì)象繼承和使用。Traits 可以用于創(chuàng)建可插拔組件、增加代碼的可讀性和可維護(hù)性,以及提供代碼的靈活性和復(fù)用性。
相關(guān)文章
python 實(shí)現(xiàn)dict轉(zhuǎn)json并保存文件
今天小編就為大家分享一篇python 實(shí)現(xiàn)dict轉(zhuǎn)json并保存文件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12Python?頁面解析Beautiful?Soup庫的使用方法
Beautiful?Soup?簡(jiǎn)稱?BS4(其中?4?表示版本號(hào))是一個(gè)?Python?中常用的頁面解析庫,它可以從?HTML?或?XML?文檔中快速地提取指定的數(shù)據(jù),這篇文章主要介紹了springboot?集成?docsify?實(shí)現(xiàn)隨身文檔?,需要的朋友可以參考下2022-09-09Python實(shí)現(xiàn)輸入若干個(gè)正整數(shù),升序后輸出
這篇文章主要介紹了Python實(shí)現(xiàn)輸入若干個(gè)正整數(shù),升序后輸出方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02