資源簡介 (共52張PPT)Python少兒編程第七章 神秘的類和對象目錄1.1“小海龜”的自我介紹1.2“小海龜”的畫布1.3“小海龜”的畫筆1.4多彩的圖畫1.5多彩的圖畫PART 01面向對象的編程世界面向對象的編程世界1傳統的程序設計方法被稱為面向過程的程序設計。面向過程程序設計的核心是過程,即解決問題的步驟。面向對象程序設計(object oriented programming,OOP)是將所有預處理的問題抽象為對象,并將相應的屬性和行為封裝起來,以提高軟件的重用性、靈活性和擴展性。現實世界中,對象就是客觀存在的某一事物,如一個人、一輛自行車等。而面向對象的編程世界中,對象具有屬性和行為兩個特征,每個對象都有各自的屬性和行為。而類是對這些具有共同特征的對象的概括、歸納和抽象表達。例如,將人抽象為“人”類,它具有名字、性別等屬性,行走、吃飯等行為,那么具體的名字為“小明”“小紅”的個體就是“人”類的對象,具體關系如圖7-1所示。面向對象的編程世界1圖7-1 類和對象的關系面向對象程序設計思想是把事物的屬性和行為包含在類中。其中,事物的屬性作為類的變量,事物的行為作為類的方法,而對象則是類的一個實例。因此,想要創建對象,需要先定義類。PART 02真實事物的抽象類的定義2.1Python中定義類的語法格式如下。class 類名:類體其中,class是Python的關鍵字,用于聲明類;類名必須是合法標識符,通常是一個有意義的名稱;類體定義類的內部實現,一般包括變量和方法的定義。定義類時應注意以下幾點。(1)類名的首字母一般需要大寫,如Car。(2)類名后必須緊跟冒號。(3)類體相對于class關鍵字必須保持一定的空格縮進。例如,定義一個Person類,包含姓名屬性和說話行為,可以用下面代碼實現。類的定義2.1class Person: #定義Person類name = '小藍' #定義姓名變量def speak(self): #定義說方法print('大家好!')在上述代碼中,使用class定義了一個名為Person的類,類中有一個name變量和一個speak()方法。從代碼中可以看出,方法的定義格式和函數是一樣的,主要區別在于,方法必須顯式地聲明一個self參數,且須位于參數列表的開頭。self參數將在7.2.3節中詳細介紹。創建對象2.2對象名 = 類名()Python中創建對象的語法格式如下。創建對象后,可以使用它來訪問類中的變量和方法,其語法格式如下。對象名.變量名對象名.方法名([參數])創建對象2.2【例7-1】 創建對象,訪問類中的變量和方法。【運行結果】 程序運行結果如圖7-2所示。【參考代碼】class Person: #定義Person類name = '小藍' #定義姓名變量def speak(self): #定義說方法print('大家好!')person = Person() #創建對象person.speak() #調用類中的方法print('我是{}'.format(person.name)) #訪問類中的變量圖7-2 例7-1程序運行結果self參數2.3在Python中,一個類可以生成無數個對象,當一個對象的方法被調用時,對象會將自身的引用作為第一個參數(即方法的self參數),傳遞給該方法。這樣,Python就知道需要操作哪個對象的方法了。帶self參數的方法也稱作實例方法,在類的實例方法中訪問實例變量時,須以self為前綴,但在外部通過對象名調用實例方法時不需要傳遞該參數。【例7-2】 self參數的使用。【參考代碼】class Person: #定義Person類def named(self, name): #定義命名的方法self.name = name #賦值def speak(self): #定義顯示名字的方法print('我的名字是{}'.format(self.name)) #輸出名字self參數2.3【運行結果】 程序運行結果如圖7-3所示。【參考代碼】xiaolan = Person() #創建對象xiaolanxiaolan.named('小藍') #xiaolan調用named()方法xiaowu = Person() #創建對象xiaowuxiaowu.named('小舞') #xiaowu調用named()方法xiaolan.speak() #xiaolan調用speak()方法xiaowu.speak() #xiaowu調用speak()方法圖7-3 例7-2程序運行結果構造方法2.4構造方法的固定名稱為__init__(),當創建類的對象時,系統會自動調用構造方法,實現對象的初始化操作。【例7-3】 構造方法示例。【參考代碼】class Person: #定義Person類#構造方法,定義變量并賦初值def __init__(self):self.name = '小藍'self.snack = '薯條'def eat(self): #定義方法,輸出變量print('{}喜歡的零食是{}'.format(self.name, self.snack))xiaolan = Person() #創建對象xiaolan.eat() #調用eat()方法構造方法2.4【運行結果】 程序運行結果如圖7-4所示。圖7-4 例7-3程序運行結果【程序說明】 在該程序中,第3~5行實現了__init__()方法,給Person類添加了name和snack屬性并賦初值,在eat()方法中訪問了name和snack的值。上例中,無論創建多少個Person類的對象,name和snack變量的初始值都是默認值。如果想要為不同對象初始化不同的值,可使用有參構造方法,即在構造方法中設置形參。創建對象時,為不同對象傳入不同的實參,并將每個對象的變量初始化為實參的值。構造方法2.4【例7-4】 有參構造方法示例。【參考代碼】class Person: #定義Person類#構造方法,定義變量并賦初值def __init__(self, name, snack):self.name = nameself.snack = snackdef eat(self): #定義方法,輸出變量print('{}喜歡的零食是{}'.format(self.name, self.snack))xiaolan = Person('小藍', '薯條') #創建對象xiaolanxiaolan.eat() #xiaolan調用eat()方法xiaowu = Person('小舞', '冰激凌') #創建對象xiaowuxiaowu.eat() #xiaowu調用eat()方法構造方法2.4【運行結果】 程序運行結果如圖7-5所示。圖7-5 例7-4程序運行結果【程序說明】 在該程序中,第3~5行定義了帶參數的構造方法,定義了兩個參數name和snack,創建對象時,可為不同對象傳入不同的參數值。析構方法2.5創建對象時,Python解釋器會默認調用構造方法;當需要刪除一個對象來釋放其所占的資源時,Python解釋器會調用析構方法。析構方法的固定名稱為__del__(),程序結束時會自動調用該方法,也可以使用del語句手動調用該方法刪除對象。【例7-5】 比較下面兩個程序,分析輸出結果。【參考代碼】【代碼一】class Person():def __init__(self): #構造方法print('---調用構造方法創建對象---')def __del__(self): #析構方法print('---調用析構方法刪除對象---')person = Person() #創建對象print('---程序結束---')析構方法2.5【參考代碼】(續)【代碼二】class Person():def __init__(self): #構造方法print('---調用構造方法創建對象---')def __del__(self): #析構方法print('---調用析構方法刪除對象---')person = Person() #創建對象del person #刪除對象print('---程序結束---')析構方法2.5【運行結果】 代碼一運行結果如圖7-6所示,代碼二運行結果如圖7-7所示。圖7-6 代碼一運行結果 圖7-7 代碼二運行結果【程序說明】 以上兩段代碼的區別在于:代碼二在程序結束前使用del語句手動調用析構方法刪除對象,因此,先輸出“---調用析構方法刪除對象---”;而代碼一沒有使用del語句,因此,在程序結束時才調用析構方法,后輸出“---調用析構方法刪除對象---”。PART 03類變量和實例變量類變量和實例變量3Python類中定義的變量包括兩種:類變量和實例變量,它們有以下兩點區別。(1)類變量是在類中所有方法外定義的;實例變量一般是指在構造方法__init__()中定義的,在類中定義和使用時必須以self作為前綴。(2)類變量屬于類,可以通過類名或對象名訪問;而實例變量屬于實例(即對象),在主程序中(或類的外部)只能通過對象名訪問。與很多面向對象程序設計語言不同,Python允許在類外部動態地為類和對象增加變這是Python動態類型特點的重要體現。提示類變量和實例變量3【參考代碼】class Toy: #定義Toy類type = '小車' #初始化類變量def __init__(self, color):self.color = color #初始化實例變量toy = Toy('紅色') #創建對象#訪問類變量和實例變量并輸出print(Toy.type, toy.type, toy.color)Toy.wheelNum = 4 #增加類變量toy.price = 5 #增加實例變量#訪問增加的類變量和實例變量并輸出print(Toy.wheelNum, toy.wheelNum, toy.price)類變量和實例變量3【運行結果】 程序運行結果如圖7-8所示。圖7-8 例7-6程序運行結果【程序說明】 Toy類中定義的type和動態為類增加的wheelNum都為類變量,因此,它們都屬于類,可以通過類名或對象名訪問。但構造方法中定義的color和動態為對象toy增加的price都為實例變量,因此,它們只能通過對象名訪問,如果用類名進行訪問會提示錯誤信息。例如,在程序的末尾增加一條語句“print(Toy.color)”,程序運行出錯,提示Toy對象沒有color屬性,運行結果如圖7-9所示。類變量和實例變量3圖7-9 錯誤提示如果類中有相同名稱的類變量和實例變量,通過對象名訪問變量時獲取的是實例變量的值,通過類名訪問變量時獲取的是類變量的值。類變量和實例變量3【例7-7】 類中有相同名稱的類變量和實例變量示例。【參考代碼】class Toy: #定義Toy類color = '白色' #初始化類變量def __init__(self):self.color = '紅色' #初始化實例變量toy = Toy() #創建對象print(Toy.color, toy.color) #訪問類變量和實例變量并輸出類變量和實例變量3【運行結果】 程序運行結果如圖7-10所示。圖7-10 例7-7程序運行結果【程序說明】 從程序運行結果可以看出,類變量和實例變量的名字相同,都為color,通過類名Toy訪問color(Toy.color)時獲取的是類變量的值“白色”,而通過對象名toy訪問color(toy.color)時獲取的是實例變量的值“紅色”。PART 04面向對象編程的三大特征封裝4.1封裝是面向對象編程的核心思想,它將對象的屬性和行為封裝起來(其載體是類),隱藏其實現細節,用戶只需通過接口來操作對象。好比用戶使用計算機時,通過鍵盤就可以實現一些功能,無須知道計算機內部是如何工作的。 具體來說,封裝有兩個層面的含義。(1)將客觀事物封裝成抽象的類,類中的變量和方法只能通過類名或對象名加“.”的方式來訪問,前面介紹的例子其實都是這一層面的封裝。(2)將類的某些變量和方法隱藏在類內部,不允許用戶直接訪問,或者留下少量的方法供外部訪問。下面重點介紹第二層面的封裝。為了更好地實現數據的封裝和保密性,可以將類中的變量和方法設置成私有的,然后在類中定義一個方法(也稱接口函數),在它內部訪問被隱藏的變量和方法,而外部可以通過接口函數進行訪問。在Python中,私有化變量或方法時只需在名字前加兩個下劃線“__”即可。封裝4.1【例7-8】 私有化變量和方法。【參考代碼】class People: #定義People類def __init__(self, name, age):self.name = nameself.__age = age #定義私有變量__agedef __sayHello(self): #定義私有方法print('Hello,大家好')def greeting(self): #定義接口函數,調用私有方法self.__sayHello()def getAge(self): #定義接口函數,返回私有變量__age的值return self.__agexiaolan = People('小藍', 10) #創建對象xiaolan.greeting() #調用接口函數#訪問實例變量和調用接口函數并輸出print('我叫{},今年{}歲了。'.format(xiaolan.name, xiaolan.getAge()))封裝4.1【運行結果】 程序運行結果如圖7-11所示。圖7-11 例7-8程序運行結果封裝4.1如果在類外部調用私有方法或訪問私有變量,就會提示錯誤信息。例如,在程序的末尾增加兩條語句“xiaolan.__sayHello()”和“print(xiaolan.__age)”,程序運行出錯,結果如圖7-12所示。出現上述問題的原因是“__sayHello()”為私有方法,類的外部無法調用類的私有方法。同理,如果程序執行到“print(xiaolan.__age)”時,也會提示類似的錯誤信息。圖7-12 錯誤提示繼承4.21.單繼承在Python中,當一個子類只有一個父類時稱為單繼承。定義子類的語法格式如下。class 子類名(父類名):子類可以繼承父類的所有公有變量和公有方法,但不能繼承其私有變量和私有方法。【例7-9】 單繼承示例。【參考代碼】class Animal: #定義Animal類type = '動物' #定義變量typefood = '食物' #定義變量fooddef eat(self): #定義方法輸出type和foodprint('{}吃{}'.format(self.type, self.food))繼承4.21.單繼承【參考代碼】(續)class Cat(Animal): #定義Cat類繼承Animal類pass #空語句cat = Cat() #創建對象cat.eat() #調用父類方法cat.type = '貓' #修改typecat.food = '魚' #修改foodcat.eat() #調用父類方法【運行結果】 程序運行結果如圖7-13所示。圖7-13 例7-9程序運行結果【程序說明】 上述代碼中定義了Animal類,包含type和food變量,以及eat()方法;然后定義了Cat子類繼承Animal類,不執行任何操作;最后創建Cat類對象,修改父類中的變量,并調用父類中的方法。從程序的運行結果可以看出,子類繼承了父類的變量和方法。繼承4.22.多繼承多繼承指一個子類可以有多個父類,它繼承了多個父類的特性。例如,沙發床是沙發和床的功能的組合,兒子喜歡做爸爸和媽媽喜歡做的事。多繼承可以看作是對單繼承的擴展,其語法格式如下。class 子類名(父類名1, 父類名2……):【例7-10】 多繼承示例。【參考代碼】class DadLikeDo: #定義DadLikeDo類def basketball(self): #定義打籃球方法print('打籃球')繼承4.22.多繼承【參考代碼】(續)class MomLikeDo: #定義MomLikeDo類def sing(self): #定義唱歌方法print('唱歌')#定義SonLikeDo類,繼承DadLikeDo類和MomLikeDo類class SonLikeDo(DadLikeDo, MomLikeDo):def dance(self): #定義跳舞方法print('跳舞')son = SonLikeDo() #創建對象print('兒子喜歡做的事:')son.basketball() #調用DadLikeDo類的方法son.sing() #調用MomLikeDo類的方法son.dance() #調用SonLikeDo類的方法繼承4.22.多繼承【運行結果】 程序運行結果如圖7-14所示。圖7-14 例7-10程序運行結果【程序說明】 上述代碼中定義了DadLikeDo類,包含basketball()方法,以及定義了MomLikeDo類,包含sing()方法;然后定義了繼承DadLikeDo類和MomLikeDo類的子類SonLikeDo,包含dance()方法;最后創建SonLikeDo類的對象,分別調用basketball()、sing()和dance()方法。從程序輸出的結果可以看出,子類同時繼承了多個父類的方法。繼承4.23.方法重寫當父類中的方法無法滿足子類需求或子類具有特有功能時,可以在子類中重寫父類的方法,即子類中的方法會覆蓋父類中同名的方法,以實現不同于父類的功能。【例7-11】 重寫父類的方法示例。【參考代碼】class Student: #定義Student類name = 'xx' #定義變量namedef category(self): #定義方法category()print(self.name + '是學生')繼承4.23.方法重寫【參考代碼】(續)class Pupil(Student): #定義Pupil類繼承Student類def category(self): #重寫category()方法print(self.name, '是小學生')class Junior(Student): #定義Junior類繼承Student類def category(self): #重寫category()方法print(self.name, '是初中生')xioalan = Pupil() #創建Pupil類對象xioalan.name = '小藍' #修改namexioalan.category() #調用category()方法xiaoming = Junior() #創建Junior類對象xiaoming.name = '小明' #修改namexiaoming.category() #調用category()方法繼承4.23.方法重寫【運行結果】 程序運行結果如圖7-15所示。圖7-15 例7-11程序運行結果【程序說明】 從程序的輸出結果可以看出,在調用Pupil類和Junior類對象的category()方法時,只調用了子類中重寫的方法,不會再調用父類的category()方法。如果需要在子類中調用父類的方法,可以使用內置函數super()或通過“父類名.方法名()”來實現。繼承4.23.方法重寫【例7-12】 子類調用父類的方法示例。【參考代碼】class Student: #定義Student類def __init__(self, name, age): #構造方法,傳遞name和ageself.name = nameself.age = agedef showInfo(self): #定義showInfo()方法,輸出name和ageprint('姓名:{};年齡:{}'.format(self.name, self.age))繼承4.23.方法重寫【參考代碼】(續)class Pupil(Student): #定義Pupil類繼承Student類#構造方法,傳遞name、age和sexdef __init__(self, name, age, sex):super().__init__(name, age) #調用父類構造方法self.sex = sexdef showInfo(self):Student.showInfo(self) #調用父類showInfo()方法print('性別:{}'.format(self.sex)) #輸出sexxiaolan = Pupil('小藍', 10, '女') #創建對象xiaolan.showInfo() #調用showInfo()方法繼承4.23.方法重寫【運行結果】 程序運行結果如圖7-16所示。圖7-16 例7-12程序運行結果【程序說明】 以上代碼中定義了Student類,在該類的__init__()方法中定義了name和age變量。然后定義了繼承Student類的子類Pupil,在該類中重寫了構造方法__init__(),使用super()函數調用父類的構造方法,并添加了自定義變量sex,使Pupil類既擁有自定義的sex,又擁有父類的name和age;還重寫了showInfo()方法,使用父類名調用了父類的showInfo()方法輸出name和age,又輸出了sex。多態4.3在Python中,多態指的是一類事物有多種形態,如一個父類有多個子類,因而多態的概念依賴于繼承。而多態性可以這樣描述:向不同的對象發送同一條消息,不同的對象在接收時會產生不同的行為(即方法)。也就是說,每個對象可以用自己的方式去響應同一消息(調用函數)。【例7-13】 多態示例。【參考代碼】class Person: #定義Person類def __init__(self, name): #構造方法,定義nameself.name = namedef who(self): #定義who()方法print('我是一個人, 我的名字是{}'.format(self.name))多態4.3【參考代碼】(續)class Student(Person): #定義Student類,繼承Person類def __init__(self, name, score): #重寫構造方法super().__init__(name)self.score = scoredef who(self): #重寫who()方法print('我是一個學生, 我的名字是{},我的語文成績是{}'.format(self.name, self.score))class Teacher(Person): #定義Teacher類,繼承Person類def __init__(self, name, course):#重寫構造方法super().__init__(name)self.course = coursedef who(self): #重寫who()方法print('我是一個老師, 我的名字是{},我教{}'.format(self.name, self.course))多態4.3【參考代碼】(續)def showInfo(x): #定義函數用于接收對象x.who() #調用who()方法#創建對象p = Person('小藍')s = Student('小明', 88)t = Teacher('唐果', '語文')#調用函數showInfo(p)showInfo(s)showInfo(t)多態4.3【運行結果】 程序運行結果如圖7-17所示。圖7-17 例7-13程序運行結果【程序說明】 上述代碼中首先定義了Person類,包含who()方法;然后定義了繼承Person類的兩個子類Student和Teacher,分別在這兩個類中重寫了who()方法;接著定義了帶參數的showInfo()函數,在該函數中調用了who()方法;最后分別創建了Person類的對象p、Student類的對象s和Teacher類的對象t,并將其作為參數調用了showInfo()函數。從程序運行結果可以看出,通過向函數中傳入不同的對象,who()方法輸出不同的結果。PART 05類方法和靜態方法類方法5.1類方法是類所擁有的方法,須用修飾器“@classmethod”來標識。對于類方法,第一個參數必須是類對象,一般以cls作為第一個參數(同self一樣只是一個習慣),可以通過對象名調用類方法,也可以通過類名調用類方法。【例7-14】 類方法示例。【參考代碼】(續)class Book: #定義Book類type = '課外書' #定義類變量并賦值#類方法,用classmethod進行修飾@classmethoddef getType(cls):return cls.type #返回類變量的值book = Book() #創建對象print(Book.getType()) #通過類名調用類方法print(book.getType()) #通過對象名調用類方法類方法5.1【運行結果】 程序運行結果如圖7-18所示。圖7-18 例7-14程序運行結果【程序說明】 上述代碼中定義了一個Book類,在其中添加了類變量type,然后在類方法getType()中返回type的值。從運行結果可以看出,用對象名調用類方法和用類名調用類方法的效果是一樣的。靜態方法5.2要在類中定義靜態方法,須在方法前加上“@staticmethod”標記符,以表示下面的方法是靜態方法。使用靜態方法的好處是,不需要實例化對象即可調用該方法。靜態方法沒有self參數,所以它無法訪問類的實例變量;靜態方法也沒有cls參數,所以它也無法訪問類變量。靜態方法既可以通過對象名調用,也可以通過類名調用。【例7-15】 靜態方法示例。【參考代碼】class Book: #定義Book類type = '課外書' #定義類變量并賦值#靜態方法,用@staticmethod進行修飾@staticmethoddef printType():print('---書的類別---')靜態方法5.2【參考代碼】(續)book = Book() #創建對象book.printType() #通過對象名調用靜態方法Book.printType() #通過類名調用靜態方法print(book.type) #輸出type【運行結果】 程序運行結果如圖7-19所示。圖7-19 例7-15程序運行結果感謝觀看 展開更多...... 收起↑ 資源預覽 縮略圖、資源來源于二一教育資源庫