面向對象思想
面向對象編程
- 類class與對象object
- 對屬於同一類事物的抽象叫類class
- 比如汽車,門,貓。
- 之前學習使用的都是Python自帶的數據類,這節課我們學習自己定義類class
- 某類事物中的一個具體的實例叫對象Object
- 比如我家的那輛汽車,張偉辦公室的大門,隔壁麗麗家的那隻小花貓。
- 類與對象的關係
- 類定義封裝了數據與方法,類就是對象的模板,可以批量生產出許多的對象。
- 比如
a=7
,7其實是整形數字int類的一個實例。那int這個類還可以’復刻’出許許多多的整形對象。這些對象共有的特徵就是:整數性。- 類(class)的變量是所有對象共享使用, 只有一個拷貝, 所有對象修改, 都可以被其他對象所見;
- 對象(object)的變量由類的每個對象所擁有, 每個對象都包含自己的一份拷貝, 不會影響其他對象;
Python中一切皆對象
#Python中的一切對象都可以使用type查看它的類
#isinstance,issubclass的使用
class Animal():
pass
class Cat(Animal):
pass
c = Cat()
#isinstance判斷一個對象實例是否屬於該類型,但是isinstance的判斷沒有type準確,它無法判斷子類的對象和父類的關係
print(isinstance(c, Cat)) # c是一隻貓
print(isinstance(c, Animal)) # 向上判斷 c是一隻動物
print(type(c) is Cat)
print(type(c) is Animal)
#issubclass判斷給定的兩個類,前者是否是後者的子類
print('\n')
print(issubclass(Cat, Animal)) # 判斷Cat類是否是Animal類的子類
print(issubclass(Animal, Cat)) # 判斷Animal類是否是Cat類的子類
輸出結果爲:
True
True
True
False
True
False
類的設計與創建
#學生類設計
#總學生的人數,全部學生的姓名,已經畢業的學生的數量
#考試功能,分數大於60分,pass,,計入總分,否則 fail
#查分功能,如果考試次數
#查所有已經畢業學員的姓名。
class Student():
student_total = 0
student_graduated=0
student_namelist=[]
student_graduated_name_list=[]
def __init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
self.__score=0
self.times=0#考試次數
Student.student_total+=1
Student.student_namelist.append(name)
def exam(self,examscore):#def函數在類中定義叫方法method,以和類外部定義的函數區分
if self.times==8:
return 'you already qualified,winner,no need to take exam again'
if examscore<60:
print('sorry,better luck next time!')
elif examscore>100:
print('you are cheating!')
else:
self.__score+=examscore
self.times+=1
print('OK!')
if self.times==8 and self.__score/self.times>80:#如果參加了八次考試,且平均分數大於80分,即可畢業
Student.student_graduated+=1
Student.student_graduated_name_list.append(self.name)
def check(self,):
if self.times<8:
return 'you need to do more {8-self.times} tests to graduate!'
elif self.__score/self.times<80:
return 'sorry,you are not qualified in ss,your mean score is {self.__score/self.times}'
else:
return 'you alreay graduated,winner!'
@classmethod
def get_graducated_student(cls,):
return cls.student_graduated
@classmethod
def get_graducated_student_list(cls,):
return cls.student_graduated_name_list
類實例化對象並使用
#實例化並使用上面創建的類,並使用
ss=Student("zhangsan",18,"男")
ss.exam(70)
ss.check()
類成員一覽
- 數據成員
- 類變量與實例變量
- 方法成員
- 類方法與實例方法
擴展閱讀:私有成員
#私有成員:對類內部的屬性及方法,通過在在標識符前加雙 下劃線__來實現的私有化
#即使是在成員名面前加了__,依舊可以訪問到。
#因爲python使用一種 name mangling 技術,將 __membername替換成 _classname__membername
ss._Student__score
輸出結果爲:
70
類中的關鍵字與裝飾器詳解
類中的關鍵字
#關鍵字
# cls
# cls是指向類的指針,在類方法中第一個形參要命名爲cls.
# self
# self是指向每個獨立對象的指針.在實例方法中第一個形參被命名爲self,以區別其它函數。
#對象方法以self參數,類方法以cls參數來傳遞。
類中的裝飾器
#這個的作用就是讓全部結果都顯示出來。
%config ZMQInteractiveShell.ast_node_interactivity='all'
#裝飾器
#@staticmethod:類靜態方法
#@classmethod:類方法
#@property—把函數調用僞裝成對屬性的訪問,數據描述符屬性的優先級高於實例名稱空間中的同名成員。
# 使用@property,不用再像java中使用getter,setter方法去設置和訪問類變量
# 這時,也只有通過@property,才能對實例變量進行訪問或設置,實現了對變量訪問的控制,
class Student1():
def __init__(self,name,age): ###__init__實例初始化
self.name = name ####self:實例變量,變量的名字叫name
self.__age=age
@property #getter
def name1(self):
return self.name
@name1.setter # setter
def name1(self,newname):
self.name = newname
@property #getter
def age(self):
return self.__age
@age.setter # setter
def age(self,newage):
self.__age = newage
# 上面這樣設置的是類變量可以被類實例隨意訪問,修改。
# 注意,這裏的name1,如果和實例變量name重名會導致,無限遞歸!!!
# RecursionError: maximum recursion depth exceeded while calling a Python object
# 但如果想讓@property和類實例變量同名呢?
# 將實例變量設置爲私有(像age一樣)就不會導致重名引發遞歸死機了
s1=Student1('jack',33)
s1.name1
s1.name1="zhangsan"
s1.name1
s1.age#getter
s1.age=22#setter
s1.age
輸出結果爲:
'jack'
'zhangsan'
33
22
擴展閱讀 魔術方法,__*__
- 魔法方法就是可以給你的類增加魔力的特殊方法,如果你的對象實現(重載)了這些方法中的某一個,那麼這個方法就會在特殊的情況下被 Python 所調用,
- 你可以定義自己想要的行爲,這些會自動發生。
- 它們經常是兩個下劃線包圍來命名的
練習題:
完成公司類的設計
- 設計以下公司類,並實例化不同對象進行檢查
- 類成員
- 類下公司的總個數
- 類方法
- 返回公司類共有多少個公司實例
- 實例變量
- 公司名,簡介,利潤,銷售額,總成本,僱員姓名,僱員人員。
- 實例方法要求有:
- 招聘人才(每招一個人會有成本產生,影響僱員列表,人數,總成本)
- 解僱人員(每解僱一個人會有成本產生,影響僱員列表,人數 ,總成本)
- 公司廣告推廣 ( 影響總成本 )
- 交社保 ( 按公司僱員總人數計算,影響總成本 )
- 交稅 ( 按公司僱員總人數計算,影響總成本 )
- 銷售(按銷售件數 * 價格計算銷售額,利潤按銷售額 * 利潤率進行計算利潤。)
- 獲取公司僱員列表
- 獲取公司淨利潤
class Company():
company_list=[]
def __init__(self,name,intro,totalcost,employees):
self.name=name
self.intro=intro
self.profit=0
self.sales=0
self.totalcost=totalcost
self.employees=employees
Company.company_list.append(name)
@classmethod
def get_company_list(cls,):
return cls.company_list
def recruit(self,newemployee,cost):
self.employees.append(newemployee)
self.totalcost-=cost
def fire(self,employeename):
self.employees.remove(employeename)
def advertising(self,cost):
self.totalcost-=cost
def social_insurance(self):
self.totalcost-=len(self.employees)*120
def pay_tax(self):
self.totalcost-=len(self.employees)*12
def sale(self,price,totalcount):
sales=price*totalcount
self.sales+=sales
self.profit+=sales*0.03
def get_employees(self):
return self.employees
def get_profit(self):
return self.profit
def get_totalcost(self):
return self.totalcost
employees=['張三1','張三2','張三3','張三4']
cc=Company('百度','介紹百度公司',10000,employees)
cc2=Company('阿里','介紹阿里公司',20000,employees)
Company.get_company_list()
cc.recruit('李四',100)
cc.fire('張三1')
cc.advertising(3000)
cc.social_insurance()
cc.pay_tax()
cc.sale(100,1000)
cc.get_employees()
cc.get_profit()
cc.get_totalcost()
輸出結果爲:
['百度', '阿里']
['張三2', '張三3', '張三4', '李四']
3000.0
6372