Python物件導向-屬性

來源:互聯網
上載者:User

標籤:err   怎麼辦   cal   初學者   job   設定   建立失敗   自動調用   recent   

屬性執行個體屬性

雖然可以通過Person類建立出xiaomingxiaohong等執行個體,但是這些執行個體看上除了地址不同外,沒有什麼其他不同。在現實世界中,區分xiaomingxiaohong要依靠他們各自的名字、性別、生日等屬性。

In [8]: student.name = 'oneTOinf'In [9]: student.gender = 'Male'In [10]: student.birth = '1995-12-24'In [11]: teacher.name = 'PianoOrRock'In [12]: teacher.school = 'LiuDu'In [13]: teacher.age = 33

執行個體的屬性可以像普通變數一樣進行操作:

In [14]: teacher.age = 33 + 1In [15]: teacher.ageOut[15]: 34
樣本

建立包含兩個 Person 類的執行個體的 list,並給兩個執行個體的 name 賦值,然後按照 name 進行排序。

In [1]: class Person(object):   ...:     pass   ...:In [2]: p1 = Person()In [3]: p1.name = 'Bart'In [4]: p2 = Person()In [5]: p2.name = 'Adam'In [6]: p3 = Person()In [7]: p3.name = 'Lisa'In [8]: L1 = [p1, p2, p3]In [9]: L2 = sorted(L1, lambda p1, p2: cmp(p1.name, p2.name))In [10]: print L2[0].nameAdamIn [11]: print L2[1].nameBartIn [12]: print L2[2].nameLisa
初始化

雖然我們可以自由地給一個執行個體綁定各種屬性,但是,現實世界中,一種類型的執行個體應該擁有相同名字的屬性。例如,Person類應該在建立的時候就擁有 namegenderbirth 屬性,怎麼辦?

在定義 Person 類時,可以為Person類添加一個特殊的__init__()方法,當建立執行個體時,__init__()方法被自動調用,我們就能在此為每個執行個體都統一加上以下屬性:

class Person(object):    def __init__(self, name, gender, birth):        self.name = name        self.gender = gender        self.birth = birth

__init__() 方法的第一個參數必須是 self(也可以用別的名字,但建議使用習慣用法),後續參數則可以自由指定,和定義函數沒有任何區別。相應地,建立執行個體時,就必須要提供除 self 以外的參數:

xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')xiaohong = Person('Xiao Hong', 'Female', '1992-2-2')

有了__init__()方法,每個Person執行個體在建立時,都會有 namegenderbirth 這3個屬性,並且,被賦予不同的屬性值,訪問屬性使用.操作符:

print xiaoming.name# 輸出 'Xiao Ming'print xiaohong.birth# 輸出 '1992-2-2'

要特別注意的是,初學者定義__init__()方法常常忘記了 self 參數:

>>> class Person(object):...     def __init__(name, gender, birth):...         pass... >>> xiaoming = Person('Xiao Ming', 'Male', '1990-1-1')Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: __init__() takes exactly 3 arguments (4 given)

這會導致建立失敗或運行不正常,因為第一個參數namePython解譯器傳入了執行個體的引用,從而導致整個方法的調用參數位置全部沒有對上。

樣本

定義Person類的__init__方法,除了接受 namegenderbirth 外,還可接受任意關鍵字參數,並把他們都作為屬性賦值給執行個體。要定義關鍵字參數,使用 **kw;除了可以直接使用self.name = ‘xxx‘設定一個屬性外,還可以通過 setattr(self, ‘name‘, ‘xxx‘)設定屬性。

class Person(object):    def __init__(self, name, gender, birth, **kw):        self.name = name        self.gender = gender        self.birth = birth        for k, v in kw.iteritems():            setattr(self, k, v)xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')print xiaoming.nameprint xiaoming.job
類屬性

類是模板,而執行個體則是根據類建立的對象。

綁定在一個執行個體上的屬性不會影響其他執行個體,但是,類本身也是一個對象,如果在類上綁定一個屬性,則所有執行個體都可以訪問類的屬性,並且,所有執行個體訪問的類屬性都是同一個!也就是說,執行個體屬性每個執行個體各自擁有,互相獨立,而類屬性有且只有一份。

定義類屬性可以直接在 class 中定義:

class Person(object):    address = 'Earth'    def __init__(self, name):        self.name = name

因為類屬性是直接綁定在類上的,所以,訪問類屬性不需要建立執行個體,就可以直接存取:

print Person.address# => Earth

對一個執行個體調用類的屬性也是可以訪問的,所有執行個體都可以訪問到它所屬的類的屬性:

p1 = Person('Bob')p2 = Person('Alice')print p1.address# => Earthprint p2.address# => Earth

由於Python是動態語言,類屬性也是可以動態添加和修改的:

Person.address = 'China'print p1.address# => 'China'print p2.address# => 'China'

因為類屬性只有一份,所以,當Person類的address改變時,所有執行個體訪問到的類屬性都改變了。

樣本

請給 Person 類添加一個類屬性 count,每建立一個執行個體,count 屬性就加 1,這樣就可以統計出一共建立了多少個 Person 的執行個體

由於建立執行個體必定會調用__init__()方法,所以在這裡修改類屬性 count 很合適。

參考代碼:

class Person(object):    count = 0    def __init__(self, name):        Person.count = Person.count + 1        self.name = namep1 = Person('Bob')print Person.count# => 1p2 = Person('Alice')print Person.count# => 2p3 = Person('Tim')print Person.count# => 3
執行個體屬性和類屬性衝突

修改類屬性會導致所有執行個體訪問到的類屬性全部都受影響,但是,如果在執行個體變數上修改類屬性會發生什麼問題呢?

class Person(object):    address = 'Earth'    def __init__(self, name):        self.name = namep1 = Person('Bob')p2 = Person('Alice')print 'Person.address = ' + Person.addressp1.address = 'China'print 'p1.address = ' + p1.addressprint 'Person.address = ' + Person.addressprint 'p2.address = ' + p2.address

結果如下:

Person.address = Earthp1.address = ChinaPerson.address = Earthp2.address = Earth

我們發現,在設定了 p1.address = ‘China‘ 後,p1訪問 address 確實變成了 ‘China‘,但是,Person.address和p2.address仍然是‘Earch‘,怎麼回事?

原因是 p1.address = ‘China‘並沒有改變 Person 的 address,而是給 p1這個執行個體綁定了執行個體屬性address ,對p1來說,它有一個執行個體屬性address(值是‘China‘),而它所屬的類Person也有一個類屬性address,所以:

訪問 p1.address 時,優先尋找執行個體屬性,返回‘China‘。

訪問 p2.address 時,p2沒有執行個體屬性address,但是有類屬性address,因此返回‘Earth‘。

可見,當執行個體屬性和類屬性重名時,執行個體屬性優先順序高,它將屏蔽掉對類屬性的訪問。

當我們把 p1 的 address 執行個體屬性刪除後,訪問 p1.address 就又返回類屬性的值 ‘Earth‘了:

del p1.addressprint p1.address# => Earth

可見,千萬不要在執行個體上修改類屬性,它實際上並沒有修改類屬性,而是給執行個體綁定了一個執行個體屬性。

樣本

請把上節的 Person 類屬性 count 改為 __count,再試試能否從執行個體和類訪問該屬性。

把count改為私人__count,這樣執行個體變數在外部無法修改__count

參考代碼:

class Person(object):    __count = 0    def __init__(self, name):        Person.__count = Person.__count + 1        self.name = name        print Person.__countp1 = Person('Bob')p2 = Person('Alice')print Person.__count

Python物件導向-屬性

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.