1、面向對象java
## 什麼是對象? - 對象是內存中專門用來存儲數據的一塊區域。 - 對象中能夠存放各類數據(好比:數字、布爾值、代碼) - 對象由三部分組成: 1.對象的標識(id) 2.對象的類型(type) 3.對象的值(value) ## 面向對象(oop) - Python是一門面向對象的編程語言 - 所謂的面向對象的語言,簡單理解就是語言中的全部操做都是經過對象來進行的 - 面向過程的編程的語言 - 面向過程指將咱們的程序的邏輯分解爲一個一個的步驟, 經過對每一個步驟的抽象,來完成程序 - 例子: - 孩子上學 1.媽媽起牀 2.媽媽上廁所 3.媽媽洗漱 4.媽媽作早飯 5.媽媽叫孩子起牀 6.孩子上廁所 7.孩子要洗漱 8.孩子吃飯 9.孩子揹着書包上學校 - 面向過程的編程思想將一個功能分解爲一個一個小的步驟, 咱們經過完成一個一個的小的步驟來完成一個程序 - 這種編程方式,符合咱們人類的思惟,編寫起來相對比較簡單 - 可是這種方式編寫代碼的每每只適用於一個功能, 若是要在實現別的功能,即便功能相差極小,也每每要從新編寫代碼, 因此它可複用性比較低,而且難於維護 - 面向對象的編程語言 - 面向對象的編程語言,關注的是對象,而不關注過程 - 對於面向對象的語言來講,一切都是對象 - 例子: 1.孩他媽起牀叫孩子上學 - 面向對象的編程思想,將全部的功能統一保存到對應的對象中 好比,媽媽功能保存到媽媽的對象中,孩子的功能保存到孩子對象中 要使用某個功能,直接找到對應的對象便可 - 這種方式編寫的代碼,比較容易閱讀,而且比較易於維護,容易複用。 - 可是這種方式編寫,不太符合常規的思惟,編寫起來稍微麻煩一點 - 簡單概括一下,面向對象的思想 1.找對象 2.搞對象 ## 類(class) - 咱們目前所學習的對象都是Python內置的對象 - 可是內置對象並不能知足全部的需求,因此咱們在開發中常常須要自定義一些對象 - 類,簡單理解它就至關於一個圖紙。在程序中咱們須要根據類來建立對象 - 類就是對象的圖紙! - 咱們也稱對象是類的實例(instance) - 若是多個對象是經過一個類建立的,咱們稱這些對象是一類對象 - 像 int() float() bool() str() list() dict() .... 這些都是類 - a = int(10) # 建立一個int類的實例 等價於 a = 10 - 咱們自定義的類都須要使用大寫字母開頭,使用大駝峯命名法(帕斯卡命名法)來對類命名 - 類也是一個對象! - 類就是一個用來建立對象的對象! - 類是type類型的對象,定義類實際上就是定義了一個type類型的對象 ## 使用類建立對象的流程(參考圖1) 1.建立一個變量 2.在內存中建立一個新對象 3.將對象的id賦值給變量 ## 類的定義(參考圖2) - 類和對象都是對現實生活中的事物或程序中的內容的抽象 - 實際上全部的事物都由兩部分構成: 1.數據(屬性) 2.行爲(方法) - 在類的代碼塊中,咱們能夠定義變量和函數, 變量會成爲該類實例的公共屬性,全部的該類實例均可以經過 對象.屬性名 的形式訪問 函數會成爲該類實例的公共方法,全部該類實例均可以經過 對象.方法名() 的形式調用方法 - 注意: 方法調用時,第一個參數由解析器自動傳遞,因此定義方法時,至少要定義一個形參! - 實例爲何能訪問到類中的屬性和方法 類中定義的屬性和方法都是公共的,任何該類實例均可以訪問 - 屬性和方法查找的流程 當咱們調用一個對象的屬性時,解析器會先在當前對象中尋找是否含有該屬性, 若是有,則直接返回當前的對象的屬性值, 若是沒有,則去當前對象的類對象中去尋找,若是有則返回類對象的屬性值, 若是類對象中依然沒有,則報錯! - 類對象和實例對象中均可以保存屬性(方法) - 若是這個屬性(方法)是全部的實例共享的,則應該將其保存到類對象中 - 若是這個屬性(方法)是某個實例獨有,則應該保存到實例對象中 - 通常狀況下,屬性保存到實例對象中 而方法須要保存到類對象中 ## 建立對象的流程 p1 = Person()的運行流程 1.建立一個變量 2.在內存中建立一個新對象 3.__init__(self)方法執行 4.將對象的id賦值給變量 ## 類的基本結構 class 類名([父類]) : 公共的屬性... # 對象的初始化方法 def __init__(self,...): ... # 其餘的方法 def method_1(self,...): ... def method_2(self,...): ... ... - 練習: 嘗試自定義一個表示狗的類(Dog) 屬性: name age gender height ... 方法: jiao() yao() run() ...
2、類的簡介編程
a = int(10) # 建立一個int類的實例 b = str('hello') # 建立一個str類的實例 # print(a , type(a)) # print(b , type(b)) # 定義一個簡單的類 # 使用class關鍵字來定義類,語法和函數很像! # class 類名([父類]): # 代碼塊 # <class '__main__.MyClass'> class MyClass(): pass # print(MyClass) # 使用MyClass建立一個對象 # 使用類來建立對象,就像調用一個函數同樣 mc = MyClass() # mc就是經過MyClass建立的對象,mc是MyClass的實例 mc_2 = MyClass() mc_3 = MyClass() mc_4 = MyClass() # mc mc_2 mc_3 mc_4 都是MyClass的實例,他們都是一類對象 # isinstance()用來檢查一個對象是不是一個類的實例 result = isinstance(mc_2,MyClass) result = isinstance(mc_2,str) # print(mc , type(mc)) # print('result =',result) # print(id(MyClass) , type(MyClass)) # 如今咱們經過MyClass這個類建立的對象都是一個空對象 # 也就是對象中實際上什麼都沒有,就至關因而一個空的盒子 # 能夠向對象中添加變量,對象中的變量稱爲屬性 # 語法:對象.屬性名 = 屬性值 mc.name = '孫悟空' mc_2.name = '豬八戒' print(mc_2.name)
# 嘗試定義一個表示人的類 class Person : # 在類的代碼塊中,咱們能夠定義變量和函數 # 在類中咱們所定義的變量,將會成爲全部的實例的公共屬性 # 全部實例均可以訪問這些變量 name = 'swk' # 公共屬性,全部實例均可以訪問 # 在類中也能夠定義函數,類中的定義的函數,咱們稱爲方法 # 這些方法能夠經過該類的全部實例來訪問 def say_hello(self) : # 方法每次被調用時,解析器都會自動傳遞第一個實參 # 第一個參數,就是調用方法的對象自己, # 若是是p1調的,則第一個參數就是p1對象 # 若是是p2調的,則第一個參數就是p2對象 # 通常咱們都會將這個參數命名爲self # say_hello()這個方法,能夠顯示以下格式的數據: # 你好!我是 xxx # 在方法中不能直接訪問類中的屬性 print('你好!我是 %s' %self.name) # 建立Person的實例 p1 = Person() p2 = Person() # print(p2.name) # 調用方法,對象.方法名() # 方法調用和函數調用的區別 # 若是是函數調用,則調用時傳幾個參數,就會有幾個實參 # 可是若是是方法調用,默認傳遞一個參數,因此方法中至少要定義一個形參 # 修改p1的name屬性 p1.name = '豬八戒' p2.name = '沙和尚' p1.say_hello() # '你好!我是 豬八戒' p2.say_hello() # '你好!我是 沙和尚' # del p2.name # 刪除p2的name屬性 # print(p1.name) # print(p2.name)
class Person : # 在類中能夠定義一些特殊方法(魔術方法) # 特殊方法都是以__開頭,__結尾的方法 # 特殊方法不須要咱們本身調用,不要嘗試去調用特殊方法 # 特殊方法將會在特殊的時刻自動調用 # 學習特殊方法: # 1.特殊方法何時調用 # 2.特殊方法有什麼做用 # 建立對象的流程 # p1 = Person()的運行流程 # 1.建立一個變量 # 2.在內存中建立一個新對象 # 3.__init__(self)方法執行 # 4.將對象的id賦值給變量 # init會在對象建立之後離開執行 # init能夠用來向新建立的對象中初始化屬性 # 調用類建立對象時,類後邊的全部參數都會依次傳遞到init()中 def __init__(self,name): # print(self) # 經過self向新建的對象中初始化屬性 self.name = name def say_hello(self): print('你們好,我是%s'%self.name) # 目前來說,對於Person類來講name是必須的,而且每個對象中的name屬性基本上都是不一樣 # 而咱們如今是將name屬性在定義爲對象之後,手動添加到對象中,這種方式很容易出現錯誤 # 咱們但願,在建立對象時,必須設置name屬性,若是不設置對象將沒法建立 # 而且屬性的建立應該是自動完成的,而不是在建立對象之後手動完成 # p1 = Person() # # 手動向對象添加name屬性 # p1.name = '孫悟空' # p2 = Person() # p2.name = '豬八戒' # p3 = Person() # p3.name = '沙和尚' # p3.say_hello() p1 = Person('孫悟空') p2 = Person('豬八戒') p3 = Person('沙和尚') p4 = Person('唐僧') # p1.__init__() 不要這麼作 # print(p1.name) # print(p2.name) # print(p3.name) # print(p4.name) p4.say_hello()
練習安全
class Dog: ''' 表示狗的類 ''' def __init__(self , name , age , gender , height): self.name = name self.age = age self.gender = gender self.height = height def jiao(self): ''' 狗叫的方法 ''' print('汪汪汪~~~') def yao(self): ''' 狗咬的方法 ''' print('我咬你~~') def run(self): print('%s 快樂的奔跑着~~'%self.name) d = Dog('小黑',8,'male',30) # 目前咱們能夠直接經過 對象.屬性 的方式來修改屬性的值,這種方式致使對象中的屬性能夠隨意修改 # 很是的不安全,值能夠任意修改,不論對錯 # 如今咱們就須要一種方式來加強數據的安全性 # 1.屬性不能隨意修改(我讓你改你才能改,不讓你改你就不能改) # 2.屬性不能修改成任意的值(年齡不能是負數) d.name = '阿黃' d.age = -10 d.run() print(d.age) # print(d.name , d.age , d.gender , d.height)
3、封裝編程語言
# 封裝是面向對象的三大特性之一 # 封裝指的是隱藏對象中一些不但願被外部所訪問到的屬性或方法 # 如何隱藏一個對象中的屬性? # - 將對象的屬性名,修改成一個外部不知道的名字 # 如何獲取(修改)對象中的屬性? # - 須要提供一個getter和setter方法使外部能夠訪問到屬性 # - getter 獲取對象中的指定屬性(get_屬性名) # - setter 用來設置對象的指定屬性(set_屬性名) # 使用封裝,確實增長了類的定義的複雜程度,可是它也確保了數據的安全性 # 1.隱藏了屬性名,使調用者沒法隨意的修改對象中的屬性 # 2.增長了getter和setter方法,很好的控制的屬性是不是隻讀的 # 若是但願屬性是隻讀的,則能夠直接去掉setter方法 # 若是但願屬性不能被外部訪問,則能夠直接去掉getter方法 # 3.使用setter方法設置屬性,能夠增長數據的驗證,確保數據的值是正確的 # 4.使用getter方法獲取屬性,使用setter方法設置屬性 # 能夠在讀取屬性和修改屬性的同時作一些其餘的處理 # 5.使用getter方法能夠表示一些計算的屬性 #java中存在set和get的做用是例如 某些屬性內部私有化外部不能訪問,因此須要set設置get取得屬性 # class Person{ # private int age ; // 聲明年齡屬性 # public void setage(int age){ // 設置年齡 # this.age = age ; # } # public int getage(){ // 取得年齡 # return age ; # } # public void tell(){ # System.out.println( "年齡:" + this.getAge()) ; # } # } # public class Demo{ # public static void main(String[] args){ # Person per = new Person() ; // 聲明並實例化對象 # per.setage(30) ; // 調用set設置年齡 # per.tell() ; // 輸出信息 # } # } class Dog: ''' 表示狗的類 ''' def __init__(self , name , age): self.hidden_name = name self.hidden_age = age def say_hello(self): print('你們好,我是 %s'%self.hidden_name) def get_name(self): ''' get_name()用來獲取對象的name屬性 ''' # print('用戶讀取了屬性') return self.hidden_name def set_name(self , name): # print('用戶修改了屬性') self.hidden_name = name def get_age(self): return self.hidden_age def set_age(self , age): if age > 0 :#限制設置年齡的條件 self.hidden_age = age d = Dog('旺財',8) # d.say_hello() # 調用setter來修改name屬性 d.set_name('小黑') d.set_age(-10) # d.say_hello() print(d.get_age())
class Rectangle: '''一個矩形的類''' def __init__ (self,width,height): #注意這裏的下劃線 左邊和右邊是英文狀態下按2次_ self.hidden_width=width self.hidden_height=height #初始化構造 def set_width(self,width):#set get構造 self.hidden_width=width def get_width(self): return self.hidden_width def set_height(self,height): self.hidden_height=height def get_height(self): return self.hidden_height def get_area(self): return self.hidden_height*self.hidden_width r=Rectangle(3,4) r.set_height(20) r.set_width(12) print(r.get_area())
# 能夠爲對象的屬性使用雙下劃線開頭,__xxx 相似於Java中的private修飾符 # 雙下劃線開頭的屬性,是對象的隱藏屬性,隱藏屬性只能在類的內部訪問,沒法經過對象訪問 # 其實隱藏屬性只不過是Python自動爲屬性改了一個名字 # 其實是將名字修改成了,_類名__屬性名 好比 __name -> _Person__name # class Person: # def __init__(self,name): # self.__name = name # def get_name(self): # return self.__name # def set_name(self , name): # self.__name = name # p = Person('孫悟空') # print(p.__name) __開頭的屬性是隱藏屬性,沒法經過對象訪問 # p.__name = '豬八戒' # print(p._Person__name) # p._Person__name = '豬八戒' # print(p.get_name()) # 使用雙下劃線__開頭的屬性,實際上依然能夠在外部訪問,因此這種方式咱們通常不用 # 通常咱們會將一些私有屬性(不但願被外部訪問的屬性)以_開頭 # 通常狀況下,使用_開頭的屬性都是私有屬性,沒有特殊須要不要修改私有屬性 class Person: def __init__(self,name): self._name = name #乾脆hidden也省略了 def get_name(self): return self._name def set_name(self , name): self._name = name p = Person('孫悟空') print(p._name)
class Person: def __init__(self,name,age): self._name = name self._age = age # property(中文意思:屬性)裝飾器,用來將一個get方法,轉換爲對象的屬性 # 添加爲property裝飾器之後,咱們就能夠像調用屬性同樣使用get方法 # 使用property裝飾的方法,必須和屬性名是同樣的 @property def name(self):#相對於get方法 注意名字的變化 print('get方法執行了~~~') return self._name # setter方法的裝飾器:@屬性名.setter @name.setter def name(self , name): #至關於set方法 print('setter方法調用了') self._name = name @property def age(self): return self._age @age.setter def age(self , age): self._age = age p = Person('豬八戒',18) p.name = '孫悟空' #像調用屬性的方式去操做方法(函數) p.age = 28 # 添加爲property裝飾器之後,咱們就能夠像調用屬性同樣使用get方法 print(p.name,p.age) #這裏原本應該寫p.name() 表示調用name方法
4、繼承ide
# 繼承 # 定義一個類 Animal(動物) # 這個類中須要兩個方法:run() sleep() class Animal: def run(self): print('動物會跑~~~') def sleep(self): print('動物睡覺~~~') # def bark(self): # print('動物嚎叫~~~') # 定義一個類 Dog(狗) # 這個類中須要三個方法:run() sleep() bark() # class Dog: # def run(self): # print('狗會跑~~~') # def sleep(self): # print('狗睡覺~~~') # def bark(self): # print('汪汪汪~~~') # 有一個類,可以實現咱們須要的大部分功能,可是不能實現所有功能 # 如何能讓這個類來實現所有的功能呢? # ① 直接修改這個類,在這個類中添加咱們須要的功能 # - 修改起來會比較麻煩,而且會違反OCP原則 # ② 直接建立一個新的類 # - 建立一個新的類比較麻煩,而且須要大量的進行復制粘貼,會出現大量的重複性代碼 # ③ 直接從Animal類中來繼承它的屬性和方法 # - 繼承是面向對象三大特性之一 # - 經過繼承咱們可使一個類獲取到其餘類中的屬性和方法 # - 在定義類時,能夠在類名後的括號中指定當前類的父類(超類、基類、super) # 子類(衍生類)能夠直接繼承父類中的全部的屬性和方法 # # 經過繼承能夠直接讓子類獲取到父類的方法或屬性,避免編寫重複性的代碼,而且也符合OCP原則 # 因此咱們常常須要經過繼承來對一個類進行擴展 class Dog(Animal): def bark(self): print('汪汪汪~~~') def run(self): print('狗跑~~~~') class Hashiqi(Dog): def fan_sha(self): print('我是一隻傻傻的哈士奇') d = Dog() h = Hashiqi() # d.run() # d.sleep() # d.bark() # r = isinstance(d , Dog) # r = isinstance(d , Animal) # print(r) # 在建立類時,若是省略了父類,則默認父類爲object # object是全部類的父類,全部類都繼承自object class Person(object): pass # issubclass() 檢查一個類是不是另外一個類的子類 # print(issubclass(Animal , Dog)) # print(issubclass(Animal , object)) # print(issubclass(Person , object)) # isinstance()用來檢查一個對象是不是一個類的實例 # 若是這個類是這個對象的父類,也會返回True # 全部的對象都是object的實例 print(isinstance(print , object))
重寫函數
# 繼承 # 定義一個類 Animal(動物) # 這個類中須要兩個方法:run() sleep() class Animal: def run(self): print('動物會跑~~~') def sleep(self): print('動物睡覺~~~') class Dog(Animal): def bark(self): print('汪汪汪~~~') def run(self): print('狗跑~~~~') # 若是在子類中若是有和父類同名的方法,則經過子類實例去調用方法時, # 會調用子類的方法而不是父類的方法,這個特色咱們成爲叫作方法的重寫(覆蓋,override) # 建立Dog類的實例 # d = Dog() # d.run() # 當咱們調用一個對象的方法時, # 會優先去當前對象中尋找是否具備該方法,若是有則直接調用 # 若是沒有,則去當前對象的父類中尋找,若是父類中有則直接調用父類中的方法, # 若是沒有,則去父類的父類中尋找,以此類推,直到找到object,若是依然沒有找到,則報錯 class A(object): def test(self): print('AAA') class B(A): def test(self): print('BBB') class C(B): def test(self): print('CCC') # 建立一個c的實例 c = C() c.test()
class Animal: def __init__(self,name): self._name = name def run(self): print('動物會跑~~~') def sleep(self): print('動物睡覺~~~') @property def name(self): return self._name @name.setter def name(self,name): self._name = name # 父類中的全部方法都會被子類繼承,包括特殊方法,也能夠重寫特殊方法 class Dog(Animal): def __init__(self,name,age): # 但願能夠直接調用父類的__init__來初始化父類中定義的屬性 # super() 能夠用來獲取當前類的父類, # 而且經過super()返回對象調用父類方法時,不須要傳遞self super().__init__(name) self._age = age def bark(self): print('汪汪汪~~~') def run(self): print('狗跑~~~~') @property def age(self): return self._age @age.setter def age(self,age): self._age = age d = Dog('旺財',18) print(d.name) print(d.age)
class A(object): def test(self): print('AAA') class B(object): def test(self): print('B中的test()方法~~') def test2(self): print('BBB') # 在Python中是支持多重繼承的,也就是咱們能夠爲一個類同時指定多個父類 # 能夠在類名的()後邊添加多個類,來實現多重繼承 # 多重繼承,會使子類同時擁有多個父類,而且會獲取到全部父類中的方法 # 在開發中沒有特殊的狀況,應該儘可能避免使用多重繼承,由於多重繼承會讓咱們的代碼過於複雜 # 若是多個父類中有同名的方法,則會如今第一個父類中尋找,而後找第二個,而後找第三個。。。 # 前邊父類的方法會覆蓋後邊父類的方法,乾爹不如親爹 class C(A,B):#一個兒子多個爸爸,Java中就不行 pass # 類名.__bases__ 這個屬性能夠用來獲取當前類的全部父類 # print(C.__bases__) (<class '__main__.B'>,) # print(B.__bases__) (<class 'object'>,) # print(C.__bases__) # (<class '__main__.A'>, <class '__main__.B'>) c = C() c.test()
多態工具
# 多態是面向對象的三大特徵之一 # 多態從字面上理解是多種形態 # 狗(狼狗、藏獒、哈士奇、古牧 。。。) # 一個對象能夠以不一樣的形態去呈現 # 定義兩個類 class A: def __init__(self,name): self._name = name @property def name(self): return self._name @name.setter def name(self,name): self._name = name class B: def __init__(self,name): self._name = name def __len__(self): return 10 @property def name(self): return self._name @name.setter def name(self,name): self._name = name class C: pass a = A('孫悟空') b = B('豬八戒') c = C() # 定義一個函數 # 對於say_hello()這個函數來講,只要對象中含有name屬性,它就能夠做爲參數傳遞 # 這個函數並不會考慮對象的類型,只要有name屬性便可 def say_hello(obj): print('你好 %s'%obj.name) # 在say_hello_2中咱們作了一個類型檢查,也就是隻有obj是A類型的對象時,才能夠正常使用, # 其餘類型的對象都沒法使用該函數,這個函數就違反了多態 # 違反了多態的函數,只適用於一種類型的對象,沒法處理其餘類型對象,這樣致使函數的適應性很是的差 # 注意,向isinstance()這種函數,在開發中通常是不會使用的! def say_hello_2(obj): # 作類型檢查 if isinstance(obj , A): print('你好 %s'%obj.name) # say_hello(b) # say_hello_2(b) # 鴨子類型 # 若是一個東西,走路像鴨子,叫聲像鴨子,那麼它就是鴨子 # len() # 之因此一個對象能經過len()來獲取長度,是由於對象中具備一個特殊方法__len__ # 換句話說,只要對象中具備__len__特殊方法,就能夠經過len()來獲取它的長度 l = [1,2,3] s = 'hello' # print(len(l)) # print(len(s)) print(len(b)) print(len(c)) # 面向對象的三大特徵: # 封裝 # - 確保對象中的數據安全 # 繼承 # - 保證了對象的可擴展性 # 多態 # - 保證了程序的靈活性
5、總結屬性和方法oop
# 定義一個類 class A(object): # 類屬性 # 實例屬性 # 類方法 # 實例方法 # 靜態方法 # 類屬性,直接在類中定義的屬性是類屬性 # 類屬性能夠經過類或類的實例訪問到 # 可是類屬性只能經過類對象來修改,沒法經過實例對象修改 count = 0 def __init__(self): # 實例屬性,經過實例對象添加的屬性屬於實例屬性 # 實例屬性只能經過實例對象來訪問和修改,類對象沒法訪問修改 self.name = '孫悟空' # 實例方法 # 在類中定義,以self爲第一個參數的方法都是實例方法 # 實例方法在調用時,Python會將調用對象做爲self傳入 # 實例方法能夠經過實例和類去調用 # 當經過實例調用時,會自動將當前調用對象做爲self傳入 # 當經過類調用時,不會自動傳遞self,此時咱們必須手動傳遞self def test(self): print('這是test方法~~~ ' , self) # 類方法 # 在類內部使用 @classmethod 來修飾的方法屬於類方法 # 類方法的第一個參數是cls,也會被自動傳遞,cls就是當前的類對象 # 類方法和實例方法的區別,實例方法的第一個參數是self,而類方法的第一個參數是cls # 類方法能夠經過類去調用,也能夠經過實例調用,沒有區別 @classmethod def test_2(cls): print('這是test_2方法,他是一個類方法~~~ ',cls) print(cls.count) # 靜態方法 # 在類中使用 @staticmethod 來修飾的方法屬於靜態方法 # 靜態方法不須要指定任何的默認參數,靜態方法能夠經過類和實例去調用 # 靜態方法,基本上是一個和當前類無關的方法,它只是一個保存到當前類中的函數 # 靜態方法通常都是一些工具方法,和當前類無關 @staticmethod def test_3(): print('test_3執行了~~~') a = A() # 實例屬性,經過實例對象添加的屬性屬於實例屬性 # a.count = 10 # A.count = 100 # print('A ,',A.count) # print('a ,',a.count) # print('A ,',A.name) # print('a ,',a.name) # a.test() 等價於 A.test(a) # A.test_2() 等價於 a.test_2() A.test_3() a.test_3()
6、垃圾回收性能
# 就像咱們生活中會產生垃圾同樣,程序在運行過程中也會產生垃圾 # 程序運行過程當中產生的垃圾會影響到程序的運行的運行性能,因此這些垃圾必須被及時清理 # 沒用的東西就是垃圾 # 在程序中沒有被引用的對象就是垃圾,這種垃圾對象過多之後會影響到程序的運行的性能 # 因此咱們必須進行及時的垃圾回收,所謂的垃圾回收就是講垃圾對象從內存中刪除 # 在Python中有自動的垃圾回收機制,它會自動將這些沒有被引用的對象刪除, # 因此咱們不用手動處理垃圾回收 class A: def __init__(self): self.name = 'A類' # del是一個特殊方法,它會在對象被垃圾回收前調用 def __del__(self): print('A()對象被刪除了~~~',self) a = A() b = a # 又使用一個變量b,來引用a對應的對象 print(a.name) # a = None # 將a設置爲了None,此時沒有任何的變量對A()對象進行引用,它就是變成了垃圾 # b = None # del a # del b input('回車鍵退出...')
# 特殊方法,也稱爲魔術方法 # 特殊方法都是使用雙下劃線__開頭和結尾的 # 特殊方法通常不須要咱們手動調用,須要在一些特殊狀況下自動執行 # 定義一個Person類 class Person(object): """人類""" def __init__(self, name , age): self.name = name self.age = age # __str__()這個特殊方法會在嘗試將對象轉換爲字符串的時候調用 # 它的做用能夠用來指定對象轉換爲字符串的結果 (print函數) def __str__(self): return 'Person [name=%s , age=%d]'%(self.name,self.age) # __repr__()這個特殊方法會在對當前對象使用repr()函數時調用 # 它的做用是指定對象在 ‘交互模式’中直接輸出的效果 def __repr__(self): return 'Hello' # object.__add__(self, other) # object.__sub__(self, other) # object.__mul__(self, other) # object.__matmul__(self, other) # object.__truediv__(self, other) # object.__floordiv__(self, other) # object.__mod__(self, other) # object.__divmod__(self, other) # object.__pow__(self, other[, modulo]) # object.__lshift__(self, other) # object.__rshift__(self, other) # object.__and__(self, other) # object.__xor__(self, other) # object.__or__(self, other) # object.__lt__(self, other) 小於 < # object.__le__(self, other) 小於等於 <= # object.__eq__(self, other) 等於 == # object.__ne__(self, other) 不等於 != # object.__gt__(self, other) 大於 > # object.__ge__(self, other) 大於等於 >= # __len__()獲取對象的長度 # object.__bool__(self) # 能夠經過bool來指定對象轉換爲布爾值的狀況 def __bool__(self): return self.age > 17 # __gt__會在對象作大於比較的時候調用,該方法的返回值將會做爲比較的結果 # 他須要兩個參數,一個self表示當前對象,other表示和當前對象比較的對象 # self > other def __gt__(self , other): return self.age > other.age # 建立兩個Person類的實例 p1 = Person('孫悟空',18) p2 = Person('豬八戒',28) # 打印p1 # 當咱們打印一個對象時,實際上打印的是對象的中特殊方法 __str__()的返回值 # print(p1) # <__main__.Person object at 0x04E95090> # print(p1) # print(p2) # print(repr(p1)) # t = 1,2,3 # print(t) # (1, 2, 3) # print(p1 > p2) # print(p2 > p1) # print(bool(p1)) # if p1 : # print(p1.name,'已經成年了') # else : # print(p1.name,'還未成年了')