類
物以類聚,人以群分,就是相同特徵的人和事物會自動聚集在一起,核心驅動點就是具有相同特徵或相類似的特徵,我們把具有相同特徵或相似特徵的事物放在一起,被稱為分類,把分類依據的特徵稱為類屬性
計算機中分類的思想叫做物件導向,Python中把資料抽象成物件,通過物件或物件間的關係來描敘資料。
我們把一些相似事物的共同特徵通過一個方式描敘出來,也就是說,你是按什麼標準對事物進行分類,相似點是什麼,計算機把對相似事物的特徵資料進行描敘稱為類定義
計算機中類的三大特徵
1. 封裝 對資料的可見性進行約束,分為公有public、私有private、非公有, 公有資料可以直接通過屬性訪問語法 obj.attr 直接訪問,但是私有、非公有則通過方法進行訪問,訪問行為其實就是SQL中的增刪改查,查稱為讀,增刪改稱為寫,在Python中類的資料稱為資料屬性,類中定義的函式稱為方法,方法是關聯物件的函式
class Person: """資料封裝實現""" def __init__(self, name, age, sex): """名字是公開的, 性別是非公有, 年齡是私有""" # 現在給例項插入資料 # 公有資料 self.name = name # 非公有使用一個下劃線 self._sex = sex # 私有變數使用兩個下劃線 self.__age = age def get_name(self): """通過方法讀取名稱""" return self.name def set_age(self, value): """對年齡進行修改""" self.__age == value def get_age(self): """通過方法獲取私有屬性年齡""" return self.__age if __name__ == '__main__': # 類的例項話類似函式呼叫,也可以使用關鍵字引數和位置引數 p = Person("北門吹雪", 20, "male") # 通過 obj.name 屬性訪問語言訪問例項的屬性,這個飯方法只能訪問公有屬性 print(p.name) # 通過方法修改年齡 p.set_age(22) # 通過方法訪問私有屬性 print(p.get_age()) pass
2. 繼承 需要理清幾個概念,父類、子類、基類、派生類,父類就是基類,子類就是派生類。繼承是建立在類的基礎上,子類完全繼承父類的所有屬性以及控制屬性訪問的方法。繼承要理清差異共相同點,對依據對事物進行分類的特徵要非常確定才能寫計算機中的類,不然不是分類,分類的前提是公共特徵,繼承的前提是共性與差異,如果不理解共同特徵你就無法分類,你不理解同一類的共性與差異你無法寫出繼承,繼承強調的是公共特徵,包括屬性和方法
class Human(object): """定義人類, 每個人類都有名字和國家, 都會說話""" def __init__(self, name, country): self.name = name self.country = country def say(self, language): """交流說話""" print(f"{self.name} 能說 {language}") class Chinese(Human): """定義一箇中國人,繼承人類 Human被稱為這個類的基類或這個類的父類,Chinese被成為Human的派生類""" def __init__(self, name, country, skin): """中國人和外國人最大的不同是膚色""" # 呼叫父類的建構函式 super(Chinese, self).__init__(name, country) self.skin = skin if __name__ == '__main__': c = Chinese("北門吹雪", 20, "yellow") print(c.skin) c.say("中文") pass
3. 多型 同一個行為具有不同表現形式或形態的能力,計算機中最接近多型的是介面interface,介面定義相同行為,然後我們對介面行為的分類,就產生所謂的抽象基類,通過繼承機制,然後子類重寫方法從而實現多型,說白了就是同一個方法中有不同的實現,再說漏骨一點就是函式的名稱相同,函式的形參相同,函式的返回值相同,但是函式體內的語句邏輯不一樣,這個函式體不同被稱為多型。多型是建立在繼承的基礎上然後對方法進行重寫,其實能重寫(又稱為過載)的只有函式體,多型強調的是方法
class HumanInterface(object): """定義一個人類的抽象介面,用於實現多型, 多型強調的是方法 定義了兩個介面,一個是吃 一個是說 """ def say(self, language): """說""" pass def eat(self, what): """吃""" pass class Chinese(HumanInterface): """定義一箇中國人,繼承人類""" def __init__(self, name, country): """中國人和外國人最大的不同是膚色""" # 呼叫父類的建構函式 self.name = name self.country = country def eat(self, what): """過載或重寫 父類中的方法,實現多型""" print(f"{self.name} 正在吃{what}ing") pass def say(self, language): print(f"{self.name} 能說 {language}") pass class American(HumanInterface): """美國人""" def __init__(self, name, country): """中國人和外國人最大的不同是膚色""" # 呼叫父類的建構函式 self.name = name self.country = country def eat(self, what): """過載或重寫 父類中的方法,實現多型""" print(f"{self.name}吃{what}再跳舞") pass def say(self, language): print(f"{self.name} 不僅能說 {language}, 還會其他國家語言") pass if __name__ == '__main__': c = Chinese("北門吹雪", "中國") a = American("alex", "美國") c.eat("大米") a.eat("漢堡包") c.say("中文") a.say("英語") # 你會發現他們方法名相同,但是輸出不同,也就是形態不同
Python中類定義
類定義
class Name: pass
# 定義是可執行的語句,在被import語句匯入或以main檔案執行時,定義就會被執行
# 類定義的執行,首先會在當前作用域引入一個用於儲存類中屬性的名稱空間。然後把這個類名稱空間封裝成物件返回,並把這個類物件繫結到class關鍵字指定的名稱,這個名稱又被繫結到class關鍵子所在的名稱空間
# Name -> 類物件 > 類名稱空間
# 其實類定義中包含的一般是函式定義,函式定義的第一個引數其實時例項本身,通過例項本身就可以訪問例項中的資料屬性和方法
類物件
# 支援兩種操作:屬性引用 和 例項化
# 屬性引用使用Python標準屬性引用語法 obj.name
# 例項化: 類的例項化,類似於函式呼叫,把括號裡的引數傳遞給類的__init__方法,通過__init__方法為類的新例項初始化特定的屬性,這個init方法又被稱為工廠函式, 其他語言中的類通過new關鍵字建立。Python中通過函式呼叫傳參的形式實現類的例項化
class Person(object): """人類""" # 能說話 can_say = True # 能吃 can_eat = True # 能睡覺 can_sleep = True def __init__(self, name, age, country): self.name = name self.__age = age self.country = country def show_country(self): """顯示國籍""" print(f"{self.name}的國籍是: {self.country}") if __name__ == '__main__': # 屬性引用 print(Person.can_eat) print(Person.can_sleep) print(Person.can_sleep) # 例項化 c = Person("北門吹雪", 20, "中國")
例項物件
# 支援唯一的操作就是屬性引用, 其實和普通的變數引用一樣,只是多個歸屬字首而已,通過方法對例項裡的變數進行修改,實際上在函式封裝過程的基礎上再把資料和函式繫結起來
class Person(object): """人類""" # 能說話 can_say = True # 能吃 can_eat = True # 能睡覺 can_sleep = True def __init__(self, name, age, country): self.name = name self.__age = age self.country = country def show_country(self): """顯示國籍""" print(f"{self.name}的國籍是: {self.country}") def set_age(self, value): """修改年齡""" self.__age = value def get_age(self): """獲取年齡""" return self.__age if __name__ == '__main__': # 例項化 user = Person("北門吹雪", 20, "中國") # 屬性引用 user_age = user.get_age() print(user_age) # 設定年齡 user.set_age(22) print(user.get_age())
方法物件
# 方法是從屬某個物件的函式,類中的函式定義了類的例項所擁有的方法,也就是說物件的型別決定了物件支援的操作
# 方法對比函式,函式定義在模組或函式中,方法定義在類定義中,方法的第一個引數固定時例項物件
類和例項變數
# 例項變數是每個例項的唯一資料,而類變數是該類的所有例項共享的屬性和方法
# 相同屬性名稱出現在類和例項中,首先被找到的時例項屬性
class Person(object): """人類""" # 該類被例項化多少次 object_count = 0 # 預設全球通用語言是英語 language = "En" def __init__(self, name, age, country, language): self.name = name self.__age = age self.country = country self.language = language def show_country(self): """顯示國籍""" print(f"{self.name}的國籍是: {self.country}") def set_age(self, value): """修改年齡""" self.__age = value def get_age(self): """獲取年齡""" return self.__age @classmethod def add_obj(cls): cls.object_count += 1 if __name__ == '__main__': # 例項化 user = Person("北門吹雪", 20, "中國", "Cn") # 例項化一次則類變數增加一次 Person.add_obj() user_two = Person("alex", 30, "美國", "En") Person.add_obj() # 列印被例項化幾次 print(Person.object_count) # 類變數和屬性同名訪問,優先選擇例項 print(user.language)