Python編程基礎(chǔ)與應(yīng)用第8章 類與對(duì)象_第1頁
Python編程基礎(chǔ)與應(yīng)用第8章 類與對(duì)象_第2頁
Python編程基礎(chǔ)與應(yīng)用第8章 類與對(duì)象_第3頁
Python編程基礎(chǔ)與應(yīng)用第8章 類與對(duì)象_第4頁
Python編程基礎(chǔ)與應(yīng)用第8章 類與對(duì)象_第5頁
已閱讀5頁,還剩82頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

8

類 與 對(duì) 象XXXX

大學(xué)XX

學(xué)院XXX

教授2學(xué)習(xí)目標(biāo):掌握定義類和創(chuàng)建對(duì)象的方法熟悉對(duì)象的屬性和方法熟悉類的封裝、繼承和多態(tài)掌握面向?qū)ο缶幊谭椒ㄋ颊?nèi)涵:面向?qū)ο蟪绦虻墓δ苁峭ㄟ^各種對(duì)象之間的協(xié)同作用實(shí)現(xiàn)的。廣大學(xué)子應(yīng)通過程序?qū)ο蟮南嗷プ饔皿w悟工作和學(xué)習(xí)中的合作意識(shí),樹立團(tuán)結(jié)協(xié)作的精神。第

8

類與對(duì)象38.1 類的定義和對(duì)象創(chuàng)建8.1.1

類的定義現(xiàn)實(shí)生活中,人們通常會(huì)對(duì)具有相似特征或行為的事物進(jìn)行命名以便區(qū)別于其他事物。同理,程序中的類也有一個(gè)名稱,也包含描述類特征的數(shù)據(jù)成員及描述類行為的成員函數(shù),其中,數(shù)據(jù)成員稱為屬性,成員函數(shù)稱為方法。Python

使用class

關(guān)鍵字來定義一個(gè)類。類的語法格式如下。class

類名:屬性名

=

屬性值def

方法名(self):方法體其中,class

關(guān)鍵字標(biāo)識(shí)類的開始;類名代表類的標(biāo)識(shí)符,使用大駝峰命名法,首字母一般為大寫字母;冒號(hào)是必不可少的;冒號(hào)之后是屬性和方法,屬4性類似于前面章節(jié)中所介紹的變量,方法類似于前面章節(jié)中所介紹的函數(shù),但方法參數(shù)列表中的第

1

個(gè)參數(shù)是一個(gè)指代對(duì)象的默認(rèn)參數(shù)self。下面定義一個(gè)表示轎車的Car

類,該類中包含描述轎車顏色的屬性color和描述轎車行駛行為的方法drive(),示例代碼如程序段P8.1

所示。P8.1

自定義類class

Car:color="red"def

drive(self):print("行駛")在定義函數(shù)時(shí)只檢測(cè)語法,不執(zhí)行代碼,但是在定義類時(shí),類體代碼會(huì)在類定義階段就立刻執(zhí)行,并且會(huì)產(chǎn)生一個(gè)類的名稱空間。也就是說,類的本身其實(shí)就是一個(gè)容器(名稱空間),用來存放名字,這是類的用途之一。第

8

類與對(duì)象58.1.2 對(duì)象創(chuàng)建與使用調(diào)用類即可產(chǎn)生對(duì)象,調(diào)用類的過程又稱為類的對(duì)象化,對(duì)象化的結(jié)果稱為類的對(duì)象。創(chuàng)建對(duì)象的語法格式如下。對(duì)象名

=

類名()根據(jù)前面定義的Car

類創(chuàng)建一個(gè)對(duì)象,代碼如下。car=Car() # car

是指向調(diào)用Car()創(chuàng)建的對(duì)象的變量對(duì)象的使用本質(zhì)上就是對(duì)類或?qū)ο蟪蓡T的使用,即訪問屬性或調(diào)用方法。訪問屬性和調(diào)用方法的語法格式如下。對(duì)象名.屬性名對(duì)象名.方法名()6例如,使用car

對(duì)象訪問color

屬性,并調(diào)用drive()方法,代碼如下。print(car.color)car.drive()運(yùn)行代碼,輸出結(jié)果如下。red行駛

8.2 屬性8.2.1

類屬性與對(duì)象屬性類的成員包括屬性和方法,默認(rèn)它們可以在類的外部被訪問或調(diào)用,但考慮到數(shù)據(jù)安全問題,有時(shí)需要將其設(shè)置為私有成員,限制類外部對(duì)其進(jìn)行訪問或調(diào)用。第

8

類與對(duì)象7屬性按聲明的方式可以分為兩類:類屬性和對(duì)象屬性。下面結(jié)合對(duì)象分別介紹類屬性和對(duì)象屬性。1.

類屬性類屬性是聲明在類內(nèi)部、方法外部的屬性。例如,示例中Car

類內(nèi)部聲明的color

屬性就是一個(gè)類屬性。類屬性可以通過類對(duì)象進(jìn)行訪問,但只能通過類進(jìn)行修改。例如,定義一個(gè)只包含類屬性的Car

類,創(chuàng)建Car

類的對(duì)象,并通過類和對(duì)象分別訪問、修改類屬性,示例代碼如程序段P8.2

所示。P8.2

定義類屬性class

Car:color="red"car=Car()8#

用類名修改屬性值#

用對(duì)象名修改屬性值print(Car.color)print(car.color)Car.color='white'print(Car.color)print(car.color)car.color='black'print(Car.color)print(car.color)運(yùn)行代碼,輸出結(jié)果如下。redredwhite第

8

類與對(duì)象9whitewhiteblack分析輸出結(jié)果中的前兩個(gè)數(shù)據(jù)可知,Car

類和car

對(duì)象成功地訪問了類屬性,結(jié)果都為“red”;分析中間的兩個(gè)數(shù)據(jù)可知,Car

類成功地修改了類屬性的值,因此Car

類和car

對(duì)象訪問的結(jié)果為“white”;分析最后兩個(gè)數(shù)據(jù)可知,Car類訪問的類屬性的值仍然是“white”,而

car

對(duì)象訪問的結(jié)果為“black”,說明car

對(duì)象不能修改類屬性的值。為什么通過

car

對(duì)象最后一次訪問類屬性的值為“

black

”?

因?yàn)椤癱ar.color='black'”語句起到了添加一個(gè)與類屬性同名的對(duì)象屬性的作用。2.

對(duì)象屬性對(duì)象屬性是在方法內(nèi)部聲明的屬性,Python

支持動(dòng)態(tài)添加對(duì)象屬性。下面10從訪問對(duì)象屬性、修改對(duì)象屬性和動(dòng)態(tài)添加對(duì)象屬性

3

個(gè)方面對(duì)對(duì)象屬性進(jìn)行介紹。1)

訪問對(duì)象屬性對(duì)象屬性只能通過對(duì)象進(jìn)行訪問。例如,定義一個(gè)包含方法和對(duì)象屬性的類Car,創(chuàng)建Car

類的對(duì)象,并訪問對(duì)象屬性,示例代碼如程序段P8.3

所示。P8.3

定義對(duì)象屬性class

Car:def

drive(self):self.color='white'car=Car()car.drive()print(car.color)第

8

類與對(duì)象11運(yùn)行代碼,輸出結(jié)果如下。white以上代碼在drive()方法中使用self

關(guān)鍵字定義了一個(gè)顏色屬性;通過對(duì)象car

成功地訪問了對(duì)象屬性。在代碼段P8.3

后面添加以下代碼。print(Car.color)運(yùn)行代碼,輸出結(jié)果如下。whiteTraceback(mostrecentcall

last):File"D:/w1.py",line8,in

<module>print(Car.color)AttributeError:

type

object

'Car'

has

no

attribute

'color'由運(yùn)行結(jié)果可知,程序通過對(duì)象

car

成功地訪問了對(duì)象屬性,當(dāng)通過類

Car12訪問對(duì)象屬性時(shí)出現(xiàn)了錯(cuò)誤,說明對(duì)象屬性只能通過對(duì)象訪問,不能通過類訪問。2)

修改對(duì)象屬性對(duì)象屬性通過對(duì)象進(jìn)行修改。例如,在以上示例中修改對(duì)象屬性的代碼如程序段P8.4

所示。P8.4

修改對(duì)象屬性class

Car:def

drive(self):self.color='white'car=Car()car.drive()print(car.color)car.color='red'第

8

類與對(duì)象13print(car.color)運(yùn)行代碼,輸出結(jié)果如下。whitered3)

動(dòng)態(tài)添加對(duì)象屬性Python

支持在類的外部使用對(duì)象動(dòng)態(tài)地添加對(duì)象屬性。例如,在以上示例的末尾動(dòng)態(tài)添加對(duì)象屬性wheels,示例代碼如程序段P8.5

所示。P8.5

添加對(duì)象屬性class

Car:def

drive(self):self.color='white'car=Car()14car.drive()print(car.color)car.wheels=4print(car.wheels)運(yùn)行代碼,輸出結(jié)果如下。white4程序成功地添加了對(duì)象屬性,并通過對(duì)象訪問了新增加的對(duì)象屬性。8.2.2

公有屬性與私有屬性Python

語言類的屬性的可見度有兩種:公有屬性和私有屬性。默認(rèn)是公有屬性,可以在類的外部通過類或?qū)ο箅S意訪問。使用雙下畫線“

”開頭的是私有屬性,僅允許類內(nèi)部訪問,類對(duì)象和派生類均不能訪問此屬性。使用單下第

8

類與對(duì)象15畫線“_”是一種約定的成員保護(hù),它表示該屬性是受保護(hù)的,只有類和子類的對(duì)象能訪問。私有屬性定義與使用的示例代碼如程序段P8.6

所示。P8.6

定義私有屬性class

Car:

color='white'car=Car()print(car.

color)運(yùn)行代碼,輸出結(jié)果如下。Traceback(mostrecentcall

last):File"D:/w1.py",line7,in

<module>print(car.

color)16AttributeError:

'Car'

object

has

no

attribute

'

color'輸出結(jié)果是異常信息,說明類的外面不能訪問類的私有屬性。如果要訪問類的私有屬性,可以通過類的公有方法來訪問。示例代碼如程序段P8.7

所示。P8.7

通過公有方法訪問私有屬性class

Car:

color='white'def

test(self):print(f"車的顏色是{self.

color}")car=Car()car.test()運(yùn)行代碼,輸出結(jié)果如下。車的顏色是white第

8

類與對(duì)象17由輸出結(jié)果可知,通過公有方法test

成功地訪問了類的私有屬性。8.2.3 特殊屬性Python

通過在屬性名稱前面和后面添加雙下畫線(

)的方式來表示特殊屬性,示例代碼如程序段P8.8

所示。P8.8

定義特殊屬性class

Car:

color

='white'car=Car()print(car.

color

)運(yùn)行代碼,輸出結(jié)果如下。white從運(yùn)行結(jié)果可知,在類的外面可以訪問特殊屬性。在編程時(shí)可以定義特殊18屬性來設(shè)計(jì)特殊功能。Python

語言已經(jīng)定義了一些特殊屬性。例如,obj.

dict

表示對(duì)象的屬性字典、obj.

class

表示對(duì)象所屬的類等。

8.3 方法對(duì)象方法、類方法、靜態(tài)方法與property

方法Python

中的方法按定義方式可以分為對(duì)象方法、類方法、靜態(tài)方法和property

方法

4

類。對(duì)象方法對(duì)象方法形似函數(shù),但它定義在類內(nèi)部,以self

為第一個(gè)形參。例如,前面聲明的drive()就是一個(gè)對(duì)象方法。對(duì)象方法中的

self

參數(shù)代表對(duì)象本身,它會(huì)在對(duì)象方法被調(diào)用時(shí)自動(dòng)接收由系統(tǒng)傳遞的調(diào)用該方法的對(duì)象。對(duì)象方法只能通過對(duì)象調(diào)用。例如,定義一個(gè)包含對(duì)象方法

drive()的類Car,第

8

類與對(duì)象19創(chuàng)建Car

類的對(duì)象,分別通過對(duì)象和類調(diào)用對(duì)象方法,示例代碼如程序段P8.9所示。P8.9

定義對(duì)象方法class

Car:def

drive(self):print('這是對(duì)象方法')car=Car()car.drive()Car.drive()運(yùn)行代碼,輸出結(jié)果如下。這是對(duì)象方法Traceback(mostrecentcall

last):20File"D:/w1.py",line7,in

<module>Car.drive()TypeError:Car.drive()missing1

requiredpositionalargument:'self'從以上結(jié)果可以看出,程序通過對(duì)象成功地調(diào)用了對(duì)象方法,通過類則無法調(diào)用對(duì)象方法。2.

類方法類方法是定義在類內(nèi)部,使用裝飾器@classmethod

修飾的方法。類方法的語法格式如下。@classmethoddef

類方法名(cls):方法體類方法中參數(shù)列表的第一個(gè)參數(shù)為cls,代表類本身,它會(huì)在類方法被調(diào)用第

8

類與對(duì)象21時(shí)自動(dòng)接收由系統(tǒng)傳遞的調(diào)用該方法的類。例如,定義一個(gè)包含類方法stop()的Car

類,示例代碼如程序段P8.10

所示。P8.10

定義類方法class

Car:@classmethoddef

stop(cls):print('這是類方法')car=Car()car.stop()Car.stop()運(yùn)行代碼,輸出結(jié)果如下。這是類方法 這是類方法22從以上結(jié)果可以看出,程序通過對(duì)象和類成功地調(diào)用了類方法。在類方法中,可以使用cls

訪問和修改類屬性的值。示例代碼如程序段P8.11所示。P8.11

在類方法中修改類屬性的值class

Car:color='black'@classmethoddef

stop(cls):print(cls.color)cls.color='red'print(cls.color)car=Car()car.stop()第

8

類與對(duì)象23運(yùn)行代碼,輸出結(jié)果如下。blackred從以上結(jié)果可以看出,程序在類方法stop()中成功地訪問和修改了類屬性color

的值。3.

靜態(tài)方法靜態(tài)方法是定義在類內(nèi)部,使用裝飾器@staticmethod

修飾的方法。靜態(tài)方法的語法格式如下。@staticmethoddef

靜態(tài)方法名():方法體24靜態(tài)方法沒有任何默認(rèn)參數(shù),它適用于與類無關(guān)的操作,或者無須使用類成員的操作,常見于一些工具類中。例如,定義一個(gè)包含靜態(tài)方法的Car

類,示例代碼如程序段P8.12

所示。P8.12

定義靜態(tài)方法class

Car:@staticmethoddef

test():print("這是靜態(tài)方法")car=Car()car.test()Car.test()運(yùn)行代碼,輸出結(jié)果如下。第

8

類與對(duì)象25這是靜態(tài)方法這是靜態(tài)方法由運(yùn)行結(jié)果可知,靜態(tài)方法可以通過類和對(duì)象調(diào)用。靜態(tài)方法內(nèi)部不能直接訪問屬性或方法,但可以使用類名訪問類屬性或調(diào)用類方法,示例代碼如程序段P8.13

所示。P8.13

通過類名訪問類屬性、調(diào)用類方法class

Car:color='black'@staticmethoddef

test():print("這是靜態(tài)方法")print(f"類屬性color

的值為{Car.color}")26car=Car()car.test()運(yùn)行代碼,輸出結(jié)果如下。這是靜態(tài)方法類屬性color

的值為black由運(yùn)行結(jié)果可知,在靜態(tài)方法test()中,通過類名成功地訪問了類屬性。4.

property

方法@property

裝飾器用來裝飾類的方法,通過@property

裝飾的方法,可以直接通過方法名調(diào)用方法,不需要在方法名后面添加圓括號(hào)。@property

裝飾器常用來裝飾訪問私有屬性的方法,以保護(hù)類的封裝特性。語法格式如下。@propertydef

方法名():第

8

類與對(duì)象27

方法體例如,定義一個(gè)帶有年齡私有屬性的人類,并定義一個(gè)@property

裝飾的方法訪問年齡私有屬性。示例代碼如程序段P8.14

所示。P8.14 @property

裝飾的方法class

Person:def

init

(self):self.

age=

18@propertydef

age(self):return

self.

ageperson=Person()print(person.age)28運(yùn)行代碼,輸出結(jié)果為

18。通過不帶括號(hào)的age

成功地訪問了私有屬性。@property

裝飾age()方法,使得該方法變成了age

屬性的getter()方法。但是,此時(shí)age

屬性只具有只讀屬性,不能修改其值。若要將其變成可寫屬性,則需要為age

屬性添加setter()方法,這時(shí)就要用到setter

裝飾器。示例代碼如程序段P8.15

所示。P8.15

@property

裝飾的方法變成了屬性class

Person:def

init

(self):self.

age=

18@propertydef

age(self):return

self.

age@age.setter第

8

類與對(duì)象29def

age(self,age):self.

age=

ageperson=Person()print(person.age)person.age=25print(person.age)運(yùn)行代碼,輸出結(jié)果為

18,25。通過age

屬性正確地修改了年齡私有屬性的值。8.3.2

公有方法與私有方法Python

語言類的方法的可見度有兩種:公有方法和私有方法。默認(rèn)是公有方法,可以在類的外部通過類或?qū)ο箅S意調(diào)用。使用雙下畫線“

”開頭的是私有方法,僅允許類內(nèi)部調(diào)用,類對(duì)象和派生類均不能調(diào)用此方法。30私有方法定義與使用的示例代碼如程序段P8.16

所示。P8.16

定義私有方法class

Car:def

drive(self):print("行駛")car=Car()car.

drive()運(yùn)行代碼,輸出結(jié)果如下。Traceback(mostrecentcall

last):File"D:/w1.py",line8,in

<module>car.

drive()AttributeError:

'Car'

object

has

no

attribute

'

drive'第

8

類與對(duì)象31輸出結(jié)果是異常信息,說明類的外面不能調(diào)用類的私有方法。如果要調(diào)用類的私有方法,可以通過類的公有方法來調(diào)用。示例代碼如程序段

P8.17

所示。P8.17

通過公有方法調(diào)用私有方法class

Car:def

drive(self):print("行駛")def

test(self):self.

drive()car=Car()car.test()運(yùn)行代碼,輸出結(jié)果如下。行駛32由運(yùn)行結(jié)果可知,通過公有方法test

成功地調(diào)用了類的私有方法。8.3.3 特殊方法Python

通過在方法名稱前面和后面添加雙下畫線(

)的方式來表示特殊方法,示例代碼如程序段P8.18

所示。P8.18

定義特殊方法class

Car:def

drive

(self):print("行駛")car=Car()car.

drive

()運(yùn)行代碼,輸出結(jié)果如下。行駛第

8

類與對(duì)象33從運(yùn)行結(jié)果可知,在類的外面可以調(diào)用特殊方法。在編程時(shí)可以定義特殊方法來設(shè)計(jì)特殊功能。Python

語言已經(jīng)定義了一些特殊方法,這些方法是基類object

自帶的,如

init

()構(gòu)造方法用來初始化對(duì)象、

del

()析構(gòu)方法用來銷毀對(duì)象、

repr

()與

str

()方法用來打印對(duì)象等。下面對(duì)構(gòu)造方法和析構(gòu)方法進(jìn)行詳細(xì)介紹。1.

構(gòu)造方法構(gòu)造方法(即

init

()方法)是類中定義的特殊方法,該方法負(fù)責(zé)在創(chuàng)建對(duì)象時(shí)對(duì)對(duì)象進(jìn)行初始化。每個(gè)類都默認(rèn)有一個(gè)

init

()方法,如果一個(gè)類中顯式地定義了

init

()方法,那么在創(chuàng)建對(duì)象時(shí)調(diào)用顯式定義的

init

()方法;否則調(diào)用默認(rèn)的

init

()方法。

init

()方法可以分為無參構(gòu)造方法和有參構(gòu)造方法。下面定義一個(gè)包含無參構(gòu)造方法和對(duì)象方法test()的Car

類,示例代碼如程34序段P8.19

所示。P8.19

無參構(gòu)造方法class

Car:def

init

(self):self.color="red"def

test(self):print(f"車的顏色:{self.color}")car=Car()car.test()運(yùn)行代碼,輸出結(jié)果如下。車的顏色:red從運(yùn)行結(jié)果可以看出,對(duì)象

car

在調(diào)用test()方法時(shí)成功地訪問了color

屬第

8

類與對(duì)象35性,說明系統(tǒng)在創(chuàng)建這個(gè)對(duì)象的同時(shí)也調(diào)用

init

()方法對(duì)其進(jìn)行了初始化。下面定義一個(gè)包含有參構(gòu)造方法和對(duì)象方法test()的Car

類,示例代碼如程序段P8.20

所示。P8.20

有參構(gòu)造方法class

Car:def

init

(self,color):self.color=colordef

test(self):print(f"車的顏色:{self.color}")car=Car("white")car.test()運(yùn)行代碼,輸出結(jié)果如下。36車的顏色:white從運(yùn)行結(jié)果可以看出,當(dāng)通過帶有參構(gòu)造方法的類

Car

創(chuàng)建對(duì)象

car

時(shí),傳入的對(duì)應(yīng)參數(shù)white

成功地對(duì)類屬性color

進(jìn)行了初始化,對(duì)象car

在調(diào)用test()方法時(shí)成功地輸出了color

屬性的值。2.

析構(gòu)方法析構(gòu)方法(即

del

()方法)是銷毀對(duì)象時(shí)系統(tǒng)自動(dòng)調(diào)用的特殊方法。每個(gè)類都默認(rèn)有一個(gè)

del

()方法。如果一個(gè)類中顯式地定義了

del

()方法,那么在銷毀該類對(duì)象時(shí)會(huì)調(diào)用顯式定義的

del

()方法;否則調(diào)用默認(rèn)的

del

()方法。下面定義一個(gè)包含構(gòu)造方法和析構(gòu)方法的Car

類,然后創(chuàng)建

Car

類的對(duì)象,之后分別在

del

語句執(zhí)行前后訪問

Car

類的對(duì)象的屬性,示例代碼如程序段P8.21

所示。第

8

類與對(duì)象37P8.21

析構(gòu)方法class

Car:def

init

(self):self.color="blue"print("對(duì)象被創(chuàng)建")def

del

(self):print("對(duì)象被銷毀")car=Car()print(car.color)delcarprint(car.color)運(yùn)行代碼,輸出結(jié)果如下。38對(duì)象被創(chuàng)建blue對(duì)象被銷毀Traceback(mostrecentcall

last):File"D:/w1.py",line10,in

<module>print(car.color)NameError:

name

'car'

is

not

defined.

Did

you

mean:

'Car'?從運(yùn)行結(jié)果可以看出,程序在刪除

Car

類的對(duì)象

car

之前成功地訪問了color

屬性;在刪除Car

類的對(duì)象car

后調(diào)用了析構(gòu)方法,打印“對(duì)象被銷毀”語句;在銷毀Car

類的對(duì)象car

后因無法使用Car

類的對(duì)象訪問屬性而出現(xiàn)錯(cuò)誤信息。與文件類似,每個(gè)對(duì)象都會(huì)占用系統(tǒng)的一部分內(nèi)存,使用之后若不及時(shí)銷第

8

類與對(duì)象39毀,就會(huì)浪費(fèi)系統(tǒng)資源。那么對(duì)象什么時(shí)候銷毀呢?Python

通過引用計(jì)數(shù)器記錄所有對(duì)象的引用數(shù)量(可以理解為對(duì)象所占內(nèi)存的別名),一旦某個(gè)對(duì)象的引用計(jì)數(shù)器的值為

0,系統(tǒng)就會(huì)銷毀這個(gè)對(duì)象,并收回對(duì)象所占用的內(nèi)存空間。

8.4 Python

的對(duì)象體系在Python

中,對(duì)象可以分為元類對(duì)象(metaclass)、類對(duì)象(class)和實(shí)例對(duì)象(instance)。元類創(chuàng)建類,類創(chuàng)建實(shí)例。Python

是一種面向?qū)ο笳Z言,所有的對(duì)象都有所屬的類型。另外,在Python

中,一切皆對(duì)象,類型也是對(duì)象,因此,Python

的實(shí)例對(duì)象有各自所屬的類型,而類型對(duì)象給定的所屬類型就是type。type

本身也是對(duì)象,如果它屬于其他類型,那么其他類型又是對(duì)象,又需要所屬的類型,這樣下去就會(huì)是無窮了,因此,type

對(duì)象的類型只能是它本身。type

的二象性是指type

是所有類對(duì)象的類型,同時(shí)

type

也是一個(gè)類對(duì)象。所有的類對(duì)象都繼承object

類對(duì)象,type

是類對(duì)象所以它繼承object;所有40的類對(duì)象的類型都是type

類型,object

是類對(duì)象所以它的類型是type。因此,type

是元類,是創(chuàng)建所有類型的類;object

是基類,是所有類都要繼承的類。通過繼承type

還可以自定義元類。元類可以動(dòng)態(tài)創(chuàng)建類。面向?qū)ο篌w系中有兩種關(guān)系:一種是類型關(guān)系,即對(duì)象所屬的類型,或者說對(duì)象是由哪個(gè)類型創(chuàng)建的;另一種是繼承關(guān)系。若把

Python

中的內(nèi)置類和用戶創(chuàng)建的類(如int、float、str、bool、tuple、dict、set

等)納入其中,就可以得到

Python

的對(duì)象體系圖(見圖

8.1),圖中顯示了所有類型關(guān)系和繼承關(guān)系。第

8

類與對(duì)象41圖

8.1

對(duì)象體系圖object

基類和type

元類是構(gòu)成Python

對(duì)象體系的基石。所有的對(duì)象都有一個(gè)生命周期,即創(chuàng)建、初始化、運(yùn)行和銷毀。Python

語言中元類的出現(xiàn)打破了很多其他面向?qū)ο笳Z言編碼時(shí)需要靜態(tài)聲明類的限制,Python

的對(duì)象模型結(jié)合了傳統(tǒng)類結(jié)構(gòu)語言的簡單性和其他模型語言的強(qiáng)大功能。428.4.1 object

基類每一個(gè)Python

類都隱含繼承了基類object。基類自帶的屬性和方法如表8-1

所示。表

8-1基類自帶的屬性和方法屬性名與方法名功能描述

class

object.

class

,返回生成該對(duì)象的類

bases

object.

bases

,返回該對(duì)象的所有父類列表

dict

object.

dict

,返回該對(duì)象的所有屬性組成的字典

doc

object.

doc

,返回類的注釋說明

module

object.

module

,返回該對(duì)象所處的模塊

new

()在調(diào)用該類時(shí)自動(dòng)觸發(fā),內(nèi)部會(huì)通過

new

產(chǎn)生一個(gè)新的對(duì)象第

8

類與對(duì)象43

init

()在調(diào)用類時(shí)自動(dòng)觸發(fā),

new

產(chǎn)生的對(duì)象調(diào)用

init

(),初始化對(duì)象

getattr

()當(dāng)通過“對(duì)象.屬性”

獲取屬性時(shí),在“沒有該屬性”

時(shí)觸發(fā)

getattribute

()當(dāng)通過“對(duì)象.屬性”

獲取屬性時(shí),“無論有沒有該屬性都會(huì)觸發(fā)

setattr

()當(dāng)“對(duì)象.屬性=屬性值”時(shí),在“添加或修改屬性”時(shí)觸發(fā)

call

()在調(diào)用對(duì)象“對(duì)象

+

(

)”時(shí)觸發(fā)

str

()在“打印對(duì)象”時(shí)觸發(fā)

getitem

()在對(duì)象通過“對(duì)象[key]”獲取屬性時(shí)觸發(fā)

setitem

()在對(duì)象通過“對(duì)象[key]=value

值”獲取屬性時(shí)觸發(fā)”44

dir

()查看屬性和方法列表

delattr

()刪除屬性

eq

()等于

gt

()大于

lt

()小于

ge

()大于等于

le

()小于等于1.

基類的

new

()方法在使用類名()創(chuàng)建對(duì)象時(shí),Python

解釋器會(huì)自動(dòng)調(diào)用

new

()方法和

init

()方法。Python

解釋器首先會(huì)調(diào)用

new

()方法在內(nèi)存中為對(duì)象分配內(nèi)存空間,然后返回對(duì)象的引用。Python

解釋器獲得對(duì)象的引用后,將引用作為第一個(gè)參數(shù)傳遞給

init

()方法,對(duì)對(duì)象進(jìn)行初始化。

new

()方法可以重第

8

類與對(duì)象45寫,重寫

new

()方法一定要返回

super().

new

(cls),否則Python

解釋器得不到分配了空間的對(duì)象引用,就不會(huì)調(diào)用對(duì)象的初始化方法。示例代碼如程序段P8.22

所示。P8.22

new

()方法無返回語句classDemo(object):def

init

(self):print("此處是

init

()方法的執(zhí)行...")def

new

(cls,*args,

**kwargs):print("此處是

new

()方法的執(zhí)行...")Demo()運(yùn)行代碼,輸出結(jié)果如下。此處是

new

()方法的執(zhí)行...46由于

new

()方法未返回對(duì)象,所有初始化方法

init

()都沒有執(zhí)行。為

new

()方法增加返回語句,修改代碼如程序段P8.23

所示。P8.23

new

()方法有返回語句class

Demo(object):def

init

(self):print("此處是

init

()方法的執(zhí)行...")def

new

(cls,*args,

**kwargs):print("此處是

new

()方法的執(zhí)行...")return

super().

new

(cls,*args,

**kwargs)Demo()運(yùn)行代碼,輸出結(jié)果如下。此處是

new

()方法的執(zhí)行...第

8

類與對(duì)象47此處是

init

()方法的執(zhí)行...

new

()方法增加返回語句后,調(diào)用了初始化方法

init

()。

new

()是一個(gè)靜態(tài)方法,在調(diào)用時(shí)需要主動(dòng)傳遞cls

參數(shù)。2.

基類的

init

()方法

init

()方法在對(duì)象生命周期中起初始化作用,每個(gè)對(duì)象必須正確初始化后才能正常工作?;恛bject

有一個(gè)默認(rèn)包含pass

init

()實(shí)現(xiàn),創(chuàng)建對(duì)象后調(diào)用該方法初始化對(duì)象。子類可以不重寫

init

()方法,在實(shí)例化子類時(shí),會(huì)自動(dòng)調(diào)用基類中已定義的

init

()方法,如果沒有對(duì)它進(jìn)行重寫,則在對(duì)象創(chuàng)建后就不會(huì)創(chuàng)建實(shí)例變量。示例代碼如程序段P8.24

所示。P8.24

不重寫

init

()方法創(chuàng)建對(duì)象class

Rectangle(object):def

area(self):48returnself.length*

self.widthr=Rectangle()r.length,r.width=13,

8print(r.area())運(yùn)行代碼,輸出結(jié)果如下。104此代碼在創(chuàng)建類時(shí),沒有重寫

init

()方法,Rectangle

類有一個(gè)使用兩個(gè)屬性來返回一個(gè)值的方法,這些屬性沒有初始化,不是實(shí)例變量。但這是合法的Python

代碼,它可以有效地避免專門設(shè)置屬性,增加了靈活性。雖然未初始化的屬性可能是有用的,但很有可能會(huì)帶來一些問題。“Python

之禪”中的建議是顯式比隱式更好。重寫

init

()方法實(shí)例化子類的情況就是上一章學(xué)習(xí)的內(nèi)容。示例代碼如程序段P8.25

所示。第

8

類與對(duì)象49P8.25

重寫

init

()方法class

Demo(object):def

init

(self):print("

init

()方法的執(zhí)行..")Demo()運(yùn)行代碼,輸出結(jié)果如下。

init

()方法的執(zhí)行..說明在創(chuàng)建對(duì)象時(shí)自動(dòng)觸發(fā)調(diào)用了重寫的

init

()方法。3.

單例設(shè)計(jì)模式設(shè)計(jì)模式是前人工作的總結(jié)和提煉,是對(duì)相關(guān)代碼進(jìn)行高層次的抽象,是針對(duì)某一特定問題的成熟的解決方案。使用設(shè)計(jì)模式可以讓代碼更容易被他人理解、保證代碼的可靠性和可重用性。如果不學(xué)習(xí)設(shè)計(jì)模式,抽象能力肯定會(huì)50受到限制。因此,若要提高編程能力,就必須學(xué)習(xí)設(shè)計(jì)模式。目前,Python

主要有

23

種設(shè)計(jì)模式,單例模式是其中之一。單例設(shè)計(jì)模式確保類創(chuàng)建的對(duì)象在系統(tǒng)中只有唯一的一個(gè)實(shí)例,每次執(zhí)行類名()返回的對(duì)象,內(nèi)存地址是相同的。單例設(shè)計(jì)模式的應(yīng)用場景有音樂播放對(duì)象、回收站對(duì)象、打印機(jī)對(duì)象等。由于

Python

創(chuàng)建對(duì)象都是在

new

()

方法中實(shí)現(xiàn)的,

因此要重寫

new

()方法,定義一個(gè)類屬性,初始值是

None,用于記錄單例對(duì)象的引用。如果類屬性為

None,則調(diào)用父類方法分配空間(即創(chuàng)建對(duì)象),并在類屬性中記錄結(jié)果,返回類屬性中記錄的對(duì)象引用。下面以設(shè)計(jì)一個(gè)單例音樂播放器為例,示例代碼如程序段P8.26

所示。P8.26

單例設(shè)計(jì)模式class

MusicPlayer(object):instance=

None第

8

類與對(duì)象51init_flag=

Falsedef

new

(cls,*args,

**kwargs):ifcls.instanceis

None:cls.instance

=

super().

new

(cls)return

cls.instancedef

init

(self):ifnot

self.init_flag:print("初始化音樂播放器")self.init_flag=

Trueplayer1=

MusicPlayer()print(player1)player2=

MusicPlayer()print(player2)52運(yùn)行代碼,輸出結(jié)果如下。初始化音樂播放器<

main

.MusicPlayerobjectat

0x00000238D77972D0><

main

.MusicPlayerobjectat

0x00000238D77972D0>代碼中對(duì)

new

()方法進(jìn)行改造之后,每次都會(huì)得到第一次被創(chuàng)建對(duì)象的引用。在

init

()方法中定義一個(gè)類屬性init_flag,標(biāo)記是否執(zhí)行過初始化動(dòng)作,初始值為False。在

init

()方法中,判斷init_flag,如果為False

就執(zhí)行初始化動(dòng)作,然后將

init_flag

設(shè)置為

True,再次自動(dòng)調(diào)用

init

()方法時(shí),初始化動(dòng)作就不會(huì)被再次執(zhí)行了。這樣,在程序運(yùn)行期間,就只有一個(gè)音樂播放器對(duì)象,實(shí)現(xiàn)了單例模式設(shè)計(jì)。8.4.2 type

元類type

是Python

的一個(gè)內(nèi)建元類,它是一個(gè)比較特殊的類,所有數(shù)據(jù)類型第

8

類與對(duì)象53都是它的實(shí)例。type

不僅可以用來查看所有對(duì)象的類型,還可以用來創(chuàng)建類,其語法格式有以下兩種。type(obj)type(name,bases,

dict)第一種語法格式用來查看某個(gè)變量(類對(duì)象)的具體類型。其中,obj

表示某個(gè)變量或類對(duì)象。第二種語法格式用來創(chuàng)建類。其中,name

表示類的名稱;bases

表示一個(gè)元組,其中存儲(chǔ)的是該類的父類;dict

表示一個(gè)字典,用于表示類內(nèi)定義的屬性或方法。示例代碼如程序段

P8.27

所示。P8.27

type

創(chuàng)建類def

say(self):print("我愛Python!")54MyClass

=

type("MyClass",(object,),dict(say

=

say,

name

=

"Python

官方文檔"))myobj=

MyClass()myobj.say()print()運(yùn)行代碼,輸出結(jié)果如下。我愛Python!Python

官方文檔可以看到,此程序中通過

type()創(chuàng)建了類,其類名為

MyClass,繼承自object

類,而且該類中還包含一個(gè)say()方法和一個(gè)name

屬性。使用type()函數(shù)創(chuàng)建的類和直接使用class

定義的類并無差別。事實(shí)上,我們?cè)谑褂胏lass定義類時(shí),Python

解釋器底層依然是調(diào)用type()來創(chuàng)建這個(gè)類的。type

最高級(jí)的用法是創(chuàng)建元類,然后用新建的元類創(chuàng)建類。使用元類就是第

8

類與對(duì)象55為了在創(chuàng)建類時(shí)能夠動(dòng)態(tài)地改變類中定義的屬性或方法,或者當(dāng)需要根據(jù)應(yīng)用場景為多個(gè)類添加某個(gè)屬性和方法時(shí),就可以先創(chuàng)建元類,然后用元類去創(chuàng)建類,最后使用該類的實(shí)例化對(duì)象實(shí)現(xiàn)功能。在創(chuàng)建新的元類時(shí),必須符合以下條件:必須顯式繼承自

type

類;類中需要定義并實(shí)現(xiàn)

new

()方法,該方法一定要返回該類的一個(gè)實(shí)例對(duì)象,因?yàn)樵谑褂迷悇?chuàng)建類時(shí),該

new

()方法會(huì)被自動(dòng)執(zhí)行,用來修改新建的類。在用元類創(chuàng)建新的類時(shí),可以在標(biāo)注父類(或不標(biāo),默認(rèn)繼承自object)的同時(shí)指定元類(格式為metaclass=元類名),這樣,當(dāng)

Python

解釋器在創(chuàng)建該類時(shí),元類中的

new

()方法就會(huì)被調(diào)用,從而實(shí)現(xiàn)動(dòng)態(tài)修改類屬性或類方法的目的。示例代碼如程序段P8.28

所示。P8.28

創(chuàng)建元類,再創(chuàng)建類class

MyMetaclass(type):def

new

(cls,name,bases,attrs):56attrs['name']=’李紅’attrs['say']=lambda

self:print('元類的say()方法')return

super().

new

(cls,name,bases,attrs)class

MyClass(object,metaclass=MyMetaclass):passmyobj=MyClass()print(myobj.name)myobj.say()運(yùn)行代碼,輸出結(jié)果如下。李紅元類的say()方法顯然,MyMetaclass

元類的

new

()方法動(dòng)態(tài)地為

MyClass

類添加了第

8

類與對(duì)象57name

屬性和say()方法,因此,即便該類在定義時(shí)是空類,它也依然有name屬性和say()方法。metaclass

元類主要用于開發(fā)應(yīng)用編程接口(API)、開發(fā)框架層面的

Python庫等中間件,而在應(yīng)用開發(fā)層面,元類的使用范圍較小。type

自帶的屬性和方法如表

8-2

所示。表

8-2 type

自帶的屬性和方法屬性名與方法名功能描述

base

返回直接父類

bases

返回所有父類列表

basicsize

返回分配的內(nèi)存空間大小

flags

返回類型標(biāo)識(shí)

mro

返回類型方法解析順序元組58

name

返回類型名稱mro()class.mro(),返回類型的方法解析順序

instancecheck

()檢查對(duì)象是否為實(shí)例

prepare

()用于為類語句創(chuàng)建命名空間

sizeof

()返回類型對(duì)象占用的內(nèi)存字節(jié)數(shù)

subclasscheck

()檢查類是否為子類1.

元類的mro()方法對(duì)于支持繼承的編程語言來說,其方法(屬性)可能定義在當(dāng)前類,也可能來自于基類,因此,在調(diào)用方法時(shí)就需要對(duì)當(dāng)前類和基類進(jìn)行搜索以確定方法所在的位置。搜索的順序即方法解析順序(method

resolution

order,MRO)。對(duì)于Python

這種支持多繼承的語言來說,MRO

比較復(fù)雜。通過

mro

屬性和mro()方法可以查看方法解析順序,示例代碼如程序段P8.29

所示。第

8

類與對(duì)象59P8.29

查看方法解析順序class

A(object):def

show(self):print

("A.show()")classB(A):

passclass

C(A):def

show(self):print(

"C.show()")classD(B,C):

passprint(D.

mro

)print(D.mro())x=D()x.show()60運(yùn)行代碼,輸出結(jié)果如下。(<class

'

main

.D'>,

<class

'

main

.B'>,

<class

'

main

.C'>,

<class

'

main

.A'>,<class

'object'>)[<class

'

main

.D'>,

<class

'

main

.B'>,

<class

'

main

.C'>,

<class

'

main

.A'>,<class

'object'>]C.show()2.

元類的

instancecheck

()方法

instancecheck

()是專門用于isinstance()內(nèi)置函數(shù),檢測(cè)一個(gè)實(shí)例是否屬于某個(gè)類的實(shí)例。這個(gè)方法一定要定義在元類中。示例代碼如程序段P8.30所示。P8.30

檢測(cè)是否為類的實(shí)例class

MyMetaclass(type):第

8

類與對(duì)象61def

instancecheck

(cls,

instance):print("

instancecheck

call")return

hasattr(instance,

"

len

")class

Demo(metaclass=MyMetaclass):passdemo=Demo()print(isinstance(demo,Demo))運(yùn)行代碼,輸出結(jié)果如下。True62抽象類抽象類的使用方式抽象類是具有抽象方法的類。抽象方法是只有方法名而沒有實(shí)現(xiàn)的方法。抽象類是一種特殊的類,只能被繼承不能被實(shí)例化,子類需要實(shí)現(xiàn)基類指定的抽象方法。類是從現(xiàn)實(shí)對(duì)象抽象而來的,抽象類是基于類抽象而來的。抽象類的編程使得每個(gè)人都可以關(guān)注當(dāng)前抽象類的方法和描述,而不需要考慮過多的實(shí)現(xiàn)細(xì)節(jié),這對(duì)于協(xié)同開發(fā)具有重要意義,同時(shí)也提高了代碼的可讀性。在不同的模塊中通過抽象基類來調(diào)用,可以用最精簡的方式展示代碼之間的邏輯關(guān)系,使模塊之間的依賴關(guān)系清晰、簡單。一個(gè)抽象類可以有多個(gè)實(shí)現(xiàn),從而使得系統(tǒng)的運(yùn)轉(zhuǎn)更加靈活。抽象類的使用方式有兩種:一是通過直接繼承創(chuàng)建子類,直接繼承抽象基類的子類必須完全覆寫(實(shí)現(xiàn))抽象基類中的“抽象”內(nèi)容后,才能被實(shí)例化,抽第

8

類與對(duì)象63象基類中可以聲明“抽象方法”和“抽象屬性”;二是注冊(cè)虛擬子類,即將其他類“注冊(cè)”為抽象類的虛擬子類(調(diào)用

register

方法),這些虛擬子類不需要直接繼承自基類,它們可以選擇實(shí)現(xiàn)抽象基類中的部分API

接口,也可以選擇不做任何實(shí)現(xiàn),但是,在使用issubclass()和issubinstance()進(jìn)行判斷時(shí)仍然會(huì)返回真值。8.5.2

abc

模塊定義抽象類Python

本身不提供抽象類和接口機(jī)制,若想實(shí)現(xiàn)抽象類,則可以借助

abc模塊。abc

模塊在

Python

中定義了抽象基類

的組件,提供了一個(gè)特殊的metaclass(元類)——ABCMeta,還定義了一些裝飾器,如@abstractmethod和

@abstractproperty。ABCMeta

用于在Python

程序中創(chuàng)建抽象基類。抽象基類如果想要聲明“抽象方法”,則可以使用@abstractmethod,如果想要64聲明“抽象屬性”,則可以使用@abstractproperty。下面定義一個(gè)File

文件抽象類,然后創(chuàng)建

Txt

文本文件子類繼承文件File類。示例代碼如程序段P8.31

所示。P8.31 abc

模塊實(shí)現(xiàn)抽象類fromabcimport

ABCMetafromabcimportabstractmethodclassFile(metaclass=

ABCMeta):#

ABCMeta

元類實(shí)現(xiàn)抽象類#

定義抽象方法,無須實(shí)現(xiàn)功能@abstractmethoddef

read(self):pass#

子類繼承抽象類,必須實(shí)現(xiàn)抽象類中的read()方法class

Txt(File):def

read(self):print('文本數(shù)據(jù)的讀取方法')第

8

類與對(duì)象65txt=

Txt()txt.read()運(yùn)行代碼,輸出結(jié)果如下。文本數(shù)據(jù)的讀取方法子類

Txt

繼承抽象基類File,并實(shí)現(xiàn)了抽象方法read()。

8.6 封裝、繼承和多態(tài)8.6.1

封裝封裝是類和對(duì)象的基本特性,它的基本思想是對(duì)外隱藏類的細(xì)節(jié),提供用于訪問類成員的公開接口。類的外部無須知道類的細(xì)節(jié),只需要使用公開接口便可訪問類的內(nèi)容,因此,在一定程度上保證了類內(nèi)數(shù)據(jù)的安全。為了符合封裝思想,在定義類時(shí)需要滿足以下兩點(diǎn)要求。66(1)

將屬性聲明為私有屬性。(2)

添加兩個(gè)供外界調(diào)用的公有方法,分別用于設(shè)置和獲取私有屬性的值。下面結(jié)合以上兩點(diǎn)要求定義一個(gè)Person

類,示例代碼如程序段P8.32

所示。P8.32

類的封裝特性class

Person:def

init

(self,name):=nameself.

age=18def

set_age(self,new_age):if

0<new_age<=150:self.

age=new_agedef

get_age(self):第

8

類與對(duì)象67return

self.

ageperson=Person("小李")print(person.get_age())person.set_age(25)print(person.get_age())運(yùn)行代碼,輸出結(jié)果如下。1825由運(yùn)行結(jié)果可知,程序獲取的私有屬性

age

的值為

25,說明屬性值設(shè)置成功。由此可知,程序只能通過類提供的兩個(gè)公有方法訪問私有屬性,這既保證了類屬性的安全,又避免了隨意給屬性賦值的現(xiàn)象。688.6.2 繼承繼承是類和對(duì)象的重要特性之一,它主要用于描述類與類之間的關(guān)系,在不改變?cè)蓄惖幕A(chǔ)上擴(kuò)展原有類的功能。若類與類之間具有繼承關(guān)系,則被繼承的類稱為父類或基類,繼承其他類的類稱為子類或派生類,子類會(huì)自動(dòng)擁有父類的公有成員。1.

單繼承單繼承即子類只繼承一個(gè)父類。Python

中單繼承的語法格式如下。class

子類名(父類)子類在繼承父類的同時(shí)會(huì)自動(dòng)擁有父類的公有成員。若在定義類時(shí)不指明該類的父類,那么該類默認(rèn)繼承基類object。下面定義一個(gè)狗類Dog

和一個(gè)繼承Dog

類的狼狗類WolfDog,示例代碼如程序段P8.33

所示。第

8

類與對(duì)象69P8.33

類的單繼承class

Dog(object):def

init

(self,color):self.color=colordef

walk(self):print("狗跳")class

WolfDog(Dog):passwolfdog=WolfDog("gray")print(wolfdog.color)wolfdog.walk()運(yùn)行代碼,輸出結(jié)果如下。70gray狗跳從以上結(jié)果可以看出,程序使用子類的對(duì)象成功地訪問了父類的屬性和方法,說明子類繼承父類后會(huì)自動(dòng)擁有父類的公有成員。子類不會(huì)擁有父類的私有成員,也不能訪問父類的私有成員。在以上示例的Dog

類中增加一個(gè)私有屬性

age

和一個(gè)私有方法

test(),示例代碼如程序段P8.34

所示。P8.34

子類不會(huì)擁有父類的私有成員class

Dog(object):def

init

(self,color):self.color=colorself.

age=18第

8

類與對(duì)象71def

walk(self):print("狗跳")def

test(self):print("私有方法")class

WolfDog(Dog):passwolfdog=WolfDog("gray")print(wolfdog.

age)wolfdog.

test()運(yùn)行代碼,會(huì)出現(xiàn)如下所示的錯(cuò)誤信息。Traceback(mostrecentcall

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論