Python中面向對象的編程
Python面向對象的編程
1概述
(1)面向對象編程
面向對象的編程是利用“類”和“對象”來創建各種模型來實現對真實世界的描述,使用面向對象編程的原因一方面是因為它可以使程序的維護和擴展變得更簡單,並且可以大大提高程序開發效率,另外,基於面向對象的程序可以使它人更加容易理解你的代碼邏輯,從而使團隊開發變得更從容。
(2)面向對象的特征
1)類(Class):一個類即是對一類擁有相同屬性的對象的抽象、藍圖、原型。在類中定義了這些對象的都具備的屬性(variables(data))、共同的方法
2)對象(Object) :一個對象即是一個類的實例化後實例,一個類必須經過實例化後方可在程序中調用,一個類可以實例化多個對象,每個對象亦可以有不同的屬性,就像人類是指所有人,每個人是指具體的對象,人與人之前有共性,亦有不同
3)封裝(Encapsulation):在類中對數據的賦值、內部調用對外部用戶是透明的,這使類變成了一個膠囊或容器,裏面包含著類的數據和方法
4)繼承(Inheritance):一個類可以派生出子類,在這個父類裏定義的屬性、方法自動被子類繼承
5)多態(Polymorphism):多態是面向對象的重要特性,簡單點說:“一個接口,多種實現”,指一個基類中派生出了不同的子類,且每個子類在繼承了同樣的方法名的同時又對父類的方法做了不同的實現,這就是同一種事物表現出的多種形態。
(3)簡單用法
class People(object): #創建一個類,類名首字母要大寫,並繼承object類 def walk(self): print "i am walking..." def talk(self): print "talking with sb..." p1 = People() #創建一個對象,屬於People類 p1.walk() #調用walk方法 p1.talk() p2 = People() p2.walk() p2.talk()
2類的方法
(1)類的方法及屬性
1)類的方法——self
類的方法(類函數)與普通的函數只有一個特別的區別——它們必須有一個額外的第一個參數名稱,但是在調用這個方法的時候你不為這個參數賦值,Python會提供這個值。這個特別的變量指對象本身,按照慣例它的名稱是self。
如你有一個類稱為MyClass和這個類的一個實例MyObject。當你調用這個對象的方法MyObject.method(arg1, arg2)的時候,這會由Python自動轉為MyClass.method(MyObject, arg1, arg2)
2)__init__()初始化
作用:對實體進行初始化
def__init__(self,name):
self.DogName= name #必須賦值self,否則類中其它函數無法調用
(3)類的方法舉例:
class People(object): info= ‘test‘ #共享變量,如果實例變量中找不到時,會找共享變量 def __init__(self,name,age,job): #構造函數(實例化函數) self.name = name #變成實例變量,即將類的局部變量變為類的全局變量 self.age = age self.job = job #self.info = ‘t2‘ #改變info的值 def walk(self): print "i am walking..." def talk(self): print "talking with sb...",People.info p1 = People("Dayi",22,"it") p2 = People("liuyi",24,"itman") p3 = People("t3",18,"ll") p1.info = "P1" print ‘P1:‘,p1.info People.info = "haha" #如果構造函數中修改了info的值,則此處再無法修改 print ‘p2:‘,p2.info print ‘p3:‘,p3.info
(4)析構函數
在實例釋放、銷毀的時候自動執行的,通常用於做一些收尾工作,如關閉一些數據庫連接,關閉打開的臨時文件。
#!/usr/bin/env python class Create_role: def __init__(self,name,age,job): self.name= name self.age =age self.job =job def show(self): print("Name:%s Age:%s Job:%s"%(self.name,self.age,self.job)) def __del__(self): #定義一個析構方法 print("%s 已經徹底清理了" %(self.name) ) r1 = Create_role("Dayi",18,"it") print(r1.name) r1.show() del r1 #在r1調用結束後,立即執行析構方法,默認在程序執行完成之後才會執行 r2 = Create_role("xiaoliu",23,"no") r2.show() r3 = Create_role("hehe",30,"bois")
(5)類的私有屬性及私有方法(類的封裝)
python默認的成員函數和成員變量都是公開的。在python中定義私有變量只需要在變量名或函數名前加上 "__"兩個下劃線,那麽這個函數或變量就會為私有的了。在內部,將 __membername替換成 _classname__membername後,你在外部使用原來的私有成員的名字時,會提示找不到,但是可以在內部調用。
class People(object): info = ‘test‘ #共享變量 def __init__(self,name,age,job): #構造函數(實例化函數) self.name = name #變成實例變量,即將類的局部變量變為類的全局變量 self.__age = age #定義一個私有屬性,方法為在屬性名前加__ self.job = job self.info = ‘t2‘ #改變info的值 self.info_dic = {"name":‘day‘, "age":"33"} def get_info(self,info_type): if info_type == ‘age‘: return self.__age elif info_type == ‘job‘: return self.job def __breath(self): #定義一個私有方法,只能在內部調用,創建方法為函數名前加__ print("%s is breathing..." %self.name) def walk(self): print "i am walking..." print(self.__breath()) #在內部調用私有方法 def talk(self): print("talking with sb...",People.info) p1 = People("Dayi",22,"it") p2 = People("liuyi",24,"itman") p1.walk() print(p1.get_info("age")) print(p1._People__age) #調用只讀屬性
3類的的繼承
Python中類可以承繼父類屬性,也可以同時繼承多個父類;形式為class 類名(父類1,父類2),子類可以繼承父類的所有方法和屬性,也可以重載父類的成員函數及屬性,須註意的是子類成員函數若重載父類(即名字相同),則會使用子類成員函數
(1)類的基本繼承
class SchoolMember(object): def __init__(self,name,age,sex): #創建父類構造函數 self.name = name self.age = age self.sex = sex def tell(self): #父類創建一個方法 print(‘‘‘--info of %s-- name:%s age :%s sex :%s ‘‘‘%(self.name,self.name,self.age,self.sex)) class Student(SchoolMember): #創建一個類,並繼承SchoolMember def __init__(self,name,age,sex,grade): #創建子類繼承函數 SchoolMember.__init__(self,name,age,sex) #讓子類的構造函數繼承父類 self.grade = grade def pay_money(self): #給子類創建一個方法 print("---%s is paying the tuition fee---" % self.name) def tell(self): SchoolMember.tell(self) #讓子類的tell()方法繼承父類 print("---from %s" % self.grade) class Teacher(SchoolMember): def __init__(self,name,age,sex,course,salary): SchoolMember.__init__(self,name,age,sex) self.course = course self.salary = salary def teaching(self): print("Teacher %s is teaching class of %s" %(self.name,self.course)) s = Student("dayi",33,"M","py s10") t = Teacher("liu",18,"M","python", 60000) s.tell() t.tell() s.pay_money() t.teaching()
(2)類的多繼承
1)繼承一:
class SchoolMember(object): def __init__(self,name,age,sex): #創建父類構造函數 self.name = name self.age = age self.sex = sex def tell(self): #父類創建一個方法 print ‘‘‘--info of %s-- name:%s age :%s sex :%s ‘‘‘%(self.name,self.name,self.age,self.sex) class School(object): def __init__(self,name,addr,tel): #再創建一個父類構造函數 self.school_name = name self.addr = addr self.tel = tel self.stu_list = [] self.tech_list = [] class Student(SchoolMember,School): #創建一個類,並繼承SchoolMember和School兩個類 def __init__(self,name,age,sex,grade): #創建子類繼承函數 SchoolMember.__init__(self,name,age,sex) #讓子類的構造函數繼承父類 School.__init__(self,"beida","shahe",999) #讓子類的構造函數繼承父類並給傳遞參數 self.grade = grade def pay_money(self): #給子類創建一個方法 print "---%s is paying the tuition fee---" % self.name def tell(self): SchoolMember.tell(self) #讓子類的tell()方法繼承父類 print ‘‘‘---from school name :%s class :%s addr :%s ‘‘‘%(self.school_name,self.grade,self.addr) s = Student("dayi",33,"M","py s10") s.tell() s.pay_money()
2)繼承二(通過super):
class School(object): def __init__(self,name,addr): self.name= name self.addr= addr self.students =[] self.staffs=[] def enroll(self,stu_obj): print("為學員%s 辦理註冊手續"%stu_obj.name ) self.students.append(stu_obj) def hire(self,staff_obj): self.staffs.append(staff_obj) print("雇傭新員工%s" % staff_obj.name) class SchoolMember(object): def __init__(self,name,age,sex): self.name= name self.age =age self.sex =sex def tell(self): pass class Teacher(SchoolMember): def __init__(self,name,age,sex,salary,course): super(Teacher,self).__init__(name,age,sex) self.salary= salary self.course= course def tell(self): print(‘‘‘ ---- info of Teacher:%s ---- Name:%s Age:%s Sex:%s Salary:%s Course:%s ‘‘‘%(self.name,self.name,self.age,self.sex,self.salary,self.course)) def teach(self): print("%s is teaching course [%s]" %(self.name,self.course)) class Student(SchoolMember): def __init__(self,name,age,sex,stu_id,grade): super(Student,self).__init__(name,age,sex) self.stu_id= stu_id self.grade= grade def tell(self): print(‘‘‘ ---- info of Student:%s ---- Name:%s Age:%s Sex:%s Stu_id:%s Grade:%s ‘‘‘ % (self.name, self.name,self.age, self.sex, self.stu_id,self.grade)) def pay_tuition(self,amount): print("%s has paid tution for $%s"% (self.name,amount) ) school = School("qinghua","海澱") #為School對象創建一個類 t1 = Teacher("day",56,"MF",200000,"Linux") t2 = Teacher("liu",22,"M",3000,"PythonDevOps") s1 = Student("dayi123",36,"MF",1001,"PythonDevOps") s2 = Student("hehe",19,"M",1002,"Linux") t1.tell() #調用Teacher類的tell()方法 s1.tell() school.hire(t1) school.enroll(s1) school.enroll(s2) print(school.students) print(school.staffs) school.staffs[0].teach()#獲取staffs列表中的第一個元素,並調用Teacher類中的teach方法 #school.students[0].pay_tuition(2000) for stu in school.students: #循環School類中的student列表的元素並賦值給stu stu.pay_tuition(5000) #調用School中的pay_tuition()方法,並傳一個參數
(3)繼承總結
py2 經典類是按深度優先來繼承的,新式類是按廣度優先來繼承的
py3 經典類和新式類都是統一按廣度優先來繼承的
4、多態(一個接口、多種實現):
多態意味著就算不知道變量所應用的對象類型是什麽,還是能對他進行操作,而它也回根據對象(或類)類型的不同而表現出不同的行為。
class Animal: def __init__(self,name): # Constructor of the class self.name= name def talk(self): #Abstract method, defined by convention only pass #raiseNotImplementedError("Subclass must implement abstract method") @staticmethod def animal_talk(obj): #將調用方法封裝在父類中 obj.talk() class Cat(Animal): def talk(self): print(‘%s :Meow!‘%self.name) class Dog(Animal): def talk(self): print(‘%s: Woof! Woof!‘%self.name) d = Dog("我c") #d.talk() c = Cat("小貓貓") #c.talk() # # def animal_talk(obj): # obj.talk() Animal.animal_talk(c) #調用c對象 Animal.animal_talk(d)
5、靜態方法和類方法
(1)靜態方法:類的靜態方法名義上歸類管理,實際上在靜態方法裏訪問不了類或實例中的任何屬性,靜態方法在創建時被裝入staticmethod類型的對象中。靜態方法創建時沒有self參數,且能夠被類本身直接調用。
(2)類方法:類方法創建時被裝入classmethod類型的對象中,類方法可以直接用類的具體對象調用,但類方法只能訪問類變量,不能訪問類的實例變量。
(3)屬性方法:類的屬性方法可以把一個類的方法變成一個類的靜態屬性。
class MyClass(object): age = 22 def __init__(self): self.name= "hehele" def sayhi(self):#必須實例化才能調用 print("---sayhi 1") @staticmethod def sayhi2():#靜態方法,跟類沒甚麽關系,不需要實例化即可調用,類的工具包 print("---sayhi 2") @staticmethod def sayhi2_2(self):#靜態方法,如果實在想傳參了,可以這樣搞 print("---sayhi 2",self.name) @classmethod def sayhi3(self):#不需要實例化即可調用,不能訪問實例數據, 訪問了實例化中的數據(self.name)調用時會報錯。 print("---sayhi 3",self.age,self.name) @property#將函數變成靜態屬性 def sayhi4(self): print("---sayhi 4",self.name) return ‘test‘ m = MyClass() m.sayhi2() m.sayhi2_2(m) #調用時將參數給參進去 print(m.sayhi4) # m.sayhi3() # MyClass.sayhi3()
類的屬性方法應用:
class Attribute(object): def __init__(self,name): self.name= name self.__food= None @property #將類的方法變成類的靜態屬性 def eat(self): print("%s eating %s......" %(self.name,self.__food)) @eat.setter #修改屬性 def eat(self,food): print("set to food:",food) self.__food= food @eat.deleter def eat(self): #刪除屬性 del self.__food d = Attribute("dayi") # print(d.__dict__) d.eat d.eat = "noodle" d.eat #修改屬性後調用屬性 del d.eat #刪除屬性 d.eat #刪除時調用屬性會報錯
6、類的成員方法
(1)__doc__
作用:獲取類的描述信息
class Dayi(): """welcome to ....""" def func(self): """func""" pass print(Dayi.__doc__) #會打印class的描述信息
(2)__module__
作用:表示當前操作的對象在那個模塊
__class__
作用:表示當前操作的對象的類是什麽
from lib import Dayi tim = Dayi print(tim.__module__) print(tim.__class__)
(3)__call__
作用:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於__call__ 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()
class Call(): def __init__(self): pass def __call__(self, *args, **kwargs): print("__call__") obj = Call() #執行__init__ obj() #執行__call__
(4)__dict__
作用:查看類或對象中的所有成員,以字典的形式顯示,
(5)__str__
作用:如果一個類中定義了__str__方法,那麽在打印 對象 時,默認輸出該方法的返回值
class Dayi(object): def dayi123(self): print("dayi123") def __str__(self): return "hello" obj = Dayi() print(obj) #沒有__str__時輸出類的內存地址,有__str__時,輸出值
(6)__getitem__、__setitem__、__delitem__
作用:用於索引操作,如字典。以上分別表示獲取、設置、刪除數據
class Foo(object): def __init__(self): self.data = {} def __getitem__(self, key): print(‘__getitem__‘, key) return self.data.get(key) #讀取字典中key的值 def __setitem__(self, key, value): print(‘__setitem__‘, key, value) self.data[key] = value #設置字典中key def __delitem__(self, key): print(‘__delitem__‘, key) del self.data[key] #刪除data中的為key的數據 obj = Foo() obj[‘name‘] = "hehe" print(obj.__dict__) print(obj.data) # del obj["name"] #刪除時自動觸發__delitem__ result = obj[‘k1‘] # 自動觸發執行 __getitem__ print(obj.__dict__) obj[‘k2‘] = ‘kk2‘ # 自動觸發執行 __setitem__ print(obj.__dict__) #查看類的字典時,類的字典內容為{‘data‘: {‘k2‘: ‘kk2‘, ‘name‘: ‘hehe‘}} del obj[‘k2‘] print(obj.__dict__)
本文出自 “dayi123” 博客,請務必保留此出處http://dayi123.blog.51cto.com/12064061/1925661
Python中面向對象的編程