一.什麼是面向對象的程序設計爲什麼要有它
1.面向過程的程序設計:核心是過程二字,過程指的是解決問題的步驟,即先幹什麼再幹什麼......面向過程的編程就好比設計一條流水線,是一種機械式的思維方式。
優點是:複雜的問題流程化,進而簡單化
缺點是:一套流水線或者流程就是用來解決一個問題,生產汽水的流水線無法生產汽車,即便是能,也得是大改,改一個組件,牽一髮而動全身。
應用場景:一旦完成基本很少改變的場景,著名的例子有Linux內核,git,以及Apache HTTP Server等
2.面向對象的程序設計:核心是對象二字,對象是特徵與技能的結合體,基於面向對象設計程序就好比在創造一個世界,你就是這個世界的上帝,存在的皆爲對象,不存在的也可以創造出來,與面向過程的思維方式形成鮮明的對比,面向對象更加重視對現實世界的模擬,是一種“上帝式”的思維方式
優點是:解決了程序的擴展性。對某一個對象單獨修改,會立刻反應在整個體系中。
缺點是:編程複雜度遠高於面向過程
應用場景:需求經常變化的軟件,一般需求的變化都集中在用戶層,互聯網應用,企業內部軟件,遊戲等都是面向對象的程序設計大顯身手的好地方
二.類與對象
類:對象是特徵與技能的結合體,而類則是一系列對象相同的特徵與技能的結合體
強調:
1.對象是具體存在的事物,而類則一個抽象的概念
2.站在不同的角度總結出的類與對象是不同的
在現實世界中:先有一個個具體存在的對象,然後隨着人類文明的發展才總結出類的概念
在程序中: 先定義類,後調用類來產生對象
1.先定義類 class OldboyStudent: #相同的特徵 school = 'oldboy' #相同的技能 def choose_course(self): print('choosing course') #類是一系列對象相同的特徵(變量)與技能(函數)的結合體,即類體中最常見的就是變量與函數的定義 # 但其實類體中是可以存在任意python代碼的 # 類體代碼會在類定義階段立即執行,會產生一個類名稱空間,用來將類體代碼執行過程中產生的名字都丟進去,查看方式如下 # print(OldboyStudent.__dict__) # 查看類的名稱空間 # print(OldboyStudent.school) #print(OldboyStudent.__dict__['school']) # print(OldboyStudent.choose_course) # OldboyStudent.school='OLDBOY' #OldboyStudent.__dict__['school']='OLDBOY' # OldboyStudent.country='China' #OldboyStudent.__dict__['country']='China' # del OldboyStudent.country # del OldboyStudent.__dict__['country'] # print(OldboyStudent.__dict__) # 總結: #1. 類本質就是一個名稱空間,或者說是一個用來存放變量與函數的容器 #2. 類的用途之一就是當做名稱空間從其內部取出名字來使用 #3. 類的用途之二是調用類來產生對象 2.後調用類來產生對象 # s1=OldboyStudent() # s2=OldboyStudent() # s3=OldboyStudent() #如此,s1、s2、s3都一樣了,而這三者除了相似的屬性之外還各種不同的屬性,這就用到了__init__ #注意:該方法是在對象產生之後纔會執行,只用來爲對象進行初始化操作,可以有任意代碼,但一定不能有返回值 class OldboyStudent: ...... def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex ...... s1=OldboyStudent('李坦克','男',18) #先調用類產生空對象s1,然後調用OldboyStudent.__init__(s1,'李坦克','男',18)s2=OldboyStudent('王大炮','女',38) s3=OldboyStudent('牛榴彈','男',78)#程序中對象的用法#執行__init__,s1.name='牛榴彈',很明顯也會產生對象的名稱空間s2.__dict__{'name': '王大炮', 'age': '女', 'sex': 38} s2.name #s2.__dict__['name']s2.name='王三炮' #s2.__dict__['name']='王三炮's2.course='python' #s2.__dict__['course']='python'del s2.course #s2.__dict__.pop('course')
!!!細說_init__方法!!!
# 方式一:爲對象初始化自己獨有的特徵 class People: country='China' x=1 def run(self): print('----->', self) # 實例化出三個空對象 obj1=People() obj2=People() obj3=People() # 爲對象定製自己獨有的特徵 obj1.name='egon' obj1.age=18 obj1.sex='male' obj2.name='lxx' obj2.age=38 obj2.sex='female' obj3.name='alex' obj3.age=38 obj3.sex='female' # print(obj1.__dict__) # print(obj2.__dict__) # print(obj3.__dict__) # print(People.__dict__) # 方式二、爲對象初始化自己獨有的特徵 class People: country='China' x=1 def __init__(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male' obj.name = x obj.age = y obj.sex = z def run(self): print('----->', self) obj1=People('egon',18,'male') #People.__init__(obj1,'egon',18,'male') obj2=People('lxx',38,'female') #People.__init__(obj2,'lxx',38,'female') obj3=People('alex',38,'female') #People.__init__(obj3,'alex',38,'female') # __init__方法 # 強調: # 1、該方法內可以有任意的python代碼 # 2、一定不能有返回值 class People: country='China' x=1 def __init__(obj, name, age, sex): #obj=obj1,x='egon',y=18,z='male' # if type(name) is not str: # raise TypeError('名字必須是字符串類型') obj.name = name obj.age = age obj.sex = sex def run(self): print('----->', self) # obj1=People('egon',18,'male') # obj1=People(3537,18,'male') # print(obj1.run) # obj1.run() #People.run(obj1) # print(People.run) !!!__init__方法之爲對象定製自己獨有的特徵
三.屬性查找
類有兩種屬性:數據屬性和函數屬性
1.類的數據屬性是所有對象共享的
2.類的函數屬性是綁定給對象用的
#類的數據屬性是所有對象共享的,id都一樣 print(id(OldboyStudent.school)) print(id(s1.school)) print(id(s2.school)) print(id(s3.school)) ************** 4377347328 4377347328 4377347328 4377347328 ************** #類的函數屬性是綁定給對象使用的,obj.method稱爲綁定方法,內存地址都不一樣 #ps:id是python的實現機制,並不能真實反映內存地址,如果有內存地址,還是以內存地址爲準 print(OldboyStudent.learn) print(s1.learn) print(s2.learn) print(s3.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會先從obj自己的名稱空間裏找name,找不到則去類中找,類也找不到就找父類...最後都找不到就拋出異常
四.綁定到對象的方法的特殊之處
#改寫 class OldboyStudent: school='oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def learn(self): print('%s is learning' %self.name) #新增self.name def eat(self): print('%s is eating' %self.name) def sleep(self): print('%s is sleeping' %self.name) s1=OldboyStudent('李坦克','男',18) s2=OldboyStudent('王大炮','女',38) s3=OldboyStudent('牛榴彈','男',78)
類中定義的函數(沒有被任何裝飾器裝飾的)是類的函數屬性,類可以使用,但必須遵循函數的參數規則,有幾個參數需要傳幾個參數
OldboyStudent.learn(s1) #李坦克 is learning OldboyStudent.learn(s2) #王大炮 is learning OldboyStudent.learn(s3) #牛榴彈 is learning
類中定義的函數(沒有被任何裝飾器裝飾的),其實主要是給對象使用的,而且是綁定到對象的,雖然所有對象指向的都是相同的功能,但是綁定到不同的對象就是不同的綁定方法
強調:綁定到對象的方法的特殊之處在於,綁定給誰就由誰來調用,誰來調用,就會將‘誰’本身當做第一個參數傳給方法,即自動傳值(方法__init__也是一樣的道理)