菜鳥學Python第二十一天
面向物件程式設計
-
兩種程式設計思想
-
面向過程:解決問題的步驟,先幹什麼後幹什麼,按照步驟一步一步就解決問題.基於該程式設計思想就好比是在編寫一條流水線,是一種機械式的思維方式.
-
優勢:複雜問題流程化,進而簡單化
-
劣勢:可拓展性差,維護性差. (實現流程是固定的,一旦中間某一個步驟發生變化,將導致整體都需要修改)
-
使用場景:對拓展性要求低的軟體,比如系統核心,指令碼等. 但是對於拓展性強的的程式就不再適合該思想程式設計,即產生了面向物件程式設計.
-
-
面向物件(OOP : object oriented programming ):物件指的是特徵和技能的結合體(基於其特徵能找到實際物體).基於該思想編寫程式就好比在創造一個世界,你就是這個世界的上帝,是一種上帝的思維方式.
-
優勢:
-
不用考慮繁瑣的實現步驟 , 從一個流水線思維變成了上帝思維
-
可拓展性高(當需要一個新功能時,寫一個具備新功能的物件,命令它去完成任務,各個物件出現問題,不會對其他物件產生影響,可維護性高)
-
-
劣勢 :
-
程式設計的複雜度高於面向過程.
-
無法準確預知結果
-
-
應用場景: 需要較高的拓展性時,(直接與使用者發生互動的程式例如:微信. qq等).......對於不需要拓展的程式而言,使用面向物件就會增加其複雜度.
-
-
-
為什麼要使用面向物件
-
在當前市場情況下,百分之九十以上的得程式都需要直接與使用者互動,而使用者的需求千變萬化,所以對程式設計的拓展性要求很高,故我們必須要使用面向物件程式設計.
-
-
類與物件
-
物件: 物件是特徵與技能的結合體(基於其特徵能找到實際對應物件)
-
類:類是一個抽象的概念,是一系列具有相同某一技能或特徵的的結合體.
-
現有物件還是先有類:
-
在現實生活中,一定是先有物件,後來隨著人類文明的發展總結的類,物件是具體存在的,而類只是一種抽象的概念
-
在程式中,務必先定義類,後呼叫類來產生物件.
在程式中特徵用變數標識,技能用函式標識
因而類中最常見的無非是:變數和函式的定義
-
-
class Student: # 定義類(類名首字母大寫) school = 'Tsinghua' # 相同特徵,變數 def learning(): # 相同技能,函式 print('learning') stu1 = Student() # 呼叫類產生物件 print(obj) # 執行結果 # <__main__.Student object at 0x0000000002648358> # 解釋以上結果:模組名為main,其中Student類下有一個指定記憶體地址為xxx的物件 print(stu.school) # 輸出物件的屬性(特徵) stu.learning() # 輸出物件的屬性(技能)
注意:1.類中可以有任意python程式碼,這些程式碼在定義類的時候便會執行
2.因而會產生新的名稱空間,用來存放類的變數名和函式名,可以通過"類名.__ dict__"檢視
3.對於經典類來說 ,我們可以通過過字典操作類名稱空間的名字,但是python為我們提供了專門的語法.
4.點是訪問屬性的語法,類中定義的名字,都是類的屬性
# 程式中類的用法 # 訪問 1,類名.變數名 # 相當於經典操作"類名.__ dict__['變數名'] 2,類名.函式名() # 相當於經典類操作"類名.__ dict__['函式名'] # 增加 類名.變數名 = 變數值 # Student.classes = '計算機一班' # 修改 類名.變數名 = 變數值 # 即如同字典的操作,更改已存在的變數(key=新value) # 刪除 del 類名.函式名 # 物件的初始化__init__:該方法是在物件產生後才會執行,只用來為物件進行初始化操作,可以有任意程式碼,但是一定不能有返回值 class Student: ...... # 函式的初始化(self一定要有,表示要初始化的物件) def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex ...... s1 = Student('jason', 23, 'male') # 相當於先呼叫類產生空物件s1,然後呼叫類.__init__(s1,'jason',23,'male') # 物件的操作,類似於類的操作 # 物件名.變數名.......
屬性查詢與繫結方法
-
屬性查詢
類有兩種屬性:資料屬性和函式屬性
-
類的資料(變數)屬性是所有物件共享的
-
類的函式屬性是繫結給物件用的(obj,method稱為繫結方法,記憶體地址都不一樣)
-
s1 = Student() s2 = Student() print(id(Student.school)) # 通過類名.變數名訪問類中資料 print(id(s1.school)) # 通過物件名訪問變數 print(id(s2.school)) 輸出結果 ''' 4377347328 4377347328 4377347328 4377347328 ''' 得出結論:類的資料是共享的,id都一致 print(id(Student.learning)) # 通過類名.函式名訪問類中資料 print(id(s1.learn)) # 通過物件名訪問函式 print(id(s2.learn)) 輸出結果: ''' <function OldboyStudent.learn at 0x1021329d8> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x1021466d8>> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146710>> <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146748>> '''
-
類中屬性查詢的順序:obj.name會先從自己的名稱空間裡找name,找不到則去類中找(類中找不到就去父類中找...最後沒找到就會報錯).
-
繫結方法
-
繫結方法:就是將物件或者類與函式進行繫結的方法,這裡的方法指的也就是函式
物件本質上就是一種存放資料的容器 函式是用於處理資料的程式碼 繫結方法就是將資料與處理資料的函式繫結在一起
-
為什麼要進行繫結:當沒有進行繫結時
-
每次傳遞引數,必須手動傳遞,很有可能傳參順序而發生錯誤
-
每次處理資料 都需要手動傳引數
-
當要處理的資料特別的多 就不能再定義為變量了 你可以使用列表出來儲存要處理的資料但是 每次處理 都需要先獲取資料 在傳遞給處理資料的函式 所以,繫結過後 可以簡化程式碼,提高效率
class Student: school = "BeiJing" def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age def learning(self): print("正在學習..") def sayHI(self): print("hello my name is %s my age:%s my sex:%s" % (self.name,self.age,self.sex)) # 預設情況下 在類中定義的函式都是繫結方法,共同點是,都會將物件作為第一個引數self stu1 = Student("一個學生","man",18) stu1.sayHI() # 當用用物件來呼叫類中的方法時,預設把物件傳入方法中 Student.sayHI(stu1) # 而用類名來呼叫時,則需要手動傳入物件
-
強調:繫結到物件的方法的特殊之處在於,繫結給誰就由誰來呼叫,誰來呼叫,就會將‘誰’本身當做第一個引數傳給方法,即自動傳值(方法init也是一樣的道理)
-
繫結給類的方法
-
繫結的方法包括兩種,常用的是繫結給物件的,另一種是繫結給類的
class Student: school = "Tsinghua" def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex # 繫結給類的方法 使用一個裝飾器叫classmethod,必須有一個引數,表示當前類,引數名也可以自己定義,建議不要修改 @classmethod def print_school(cls): # 輸出類裡面叫school的屬性 print(cls.school) # def print_school2(self): # 輸出類裡面叫school的屬性 # print(self.school) # 這是繫結給物件的方法 def sayHello(self): print(self.name, " 說: 你好") # Student.print_school_name() Student.print_school()
-
一個方法到底應該繫結給物件還是幫對給類? 當要處理的資料包含在類中時,就應該繫結給類 當要處理的資料包含在物件中時,就應該繫結給物件
-
繫結給物件和繫結給類的差別
-
物件繫結方法 可以使用物件來呼叫 也可以使用類名來呼叫 在物件呼叫時會自動傳入物件自己
-
類呼叫時不會自動傳參
類的繫結方法,物件和類都能呼叫,並且都會自動傳入這個類
-
-
-
非繫結方法(瞭解)
class Teacher: def __init__(self,name,sex): self.name = name self.sex = sex # @staticmethod 用於定義個非繫結方法 @staticmethod def test_func(num): print("test_func run!") print(num) Teacher.test_func(1) t1 = Teacher("矮根","男") t1.test_func(100) print(t1.test_func) # 什麼是非繫結方法 再類中 即不繫結給類 也不繫結給物件 # 特點:沒有自動傳引數的效果 ,類和物件向都能呼叫,就是一個普通函式 # 當你的這個功能不需要訪問類的資料 也不需要訪問物件的資料,就可以作為一個非繫結方法 # 使用場景較少