類即類別、種類,是面向對象設計最重要的概念,對象是特徵與技能的結合體,類就是一系列對象類似特徵和技能的結合體,針對一樣的事物,站在不一樣的角度獲得的類是不一樣的。須要注意的是:python
在現實世界中必定是先有對象後有類;但在程序中,倒是偏偏相反,必定是先定義類,後調用類來產生對象。sql
# 先定義類 class LuffyStudent: school = 'luffycity' def learn(self): print('is learning') def eat(self): print('is eating') def sleep(self): print('is sleeping') # 後產生對象 stu1 = LuffyStudent() # 不是執行類體,而是實例化 stu2 = LuffyStudent() stu3 = LuffyStudent() print(stu1) # <__main__.LuffyStudent object at 0x10401ae80>
注意:編程
__dict__是一個字典,鍵爲屬性名,值爲屬性值。類的__dict__存儲全部實例共享的變量和函數(類屬性,方法等),類的__dict__並不包含其父類的屬性。app
class LuffyStudent: school = 'luffycity' def learn(self): print('is learning') def eat(self): print('is sleeping') print(LuffyStudent.__dict__) print(LuffyStudent.__dict__['school']) print(LuffyStudent.__dict__['learn']) """ {'__module__': '__main__', 'school': 'luffycity', 'learn': <function LuffyStudent.learn at 0x101eb3620>, 'eat': <function LuffyStudent.eat at 0x101f211e0>, '__dict__': <attribute '__dict__' of 'LuffyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'LuffyStudent' objects>, '__doc__': None} luffycity <function LuffyStudent.learn at 0x101eb3620> """
一、dir()是Python提供的一個API函數,dir()函數會自動尋找一個對象的全部屬性(包括從父類繼承的屬性),包括__dict__中的屬性。ide
二、__dict__是dir()的子集,一個實例的__dict__屬性僅僅是那個實例的實例屬性的集合,並不包含該實例的全部有效屬性。函數
__name__:查看類的名字(這裏的類名是字符串類型的)ui
__dict__:查出一個字典,key爲屬性名,value爲屬性值spa
__doc__:顯示註釋設計
dir(類名):查看類,以列表的形式顯示出來code
__module__:類定義所在的模塊
__class__:
isinstance(stu1, LuffyStudent):判斷對象是不是類的實例
在使用類時,能夠對類的屬性進行增刪改查操做。
class LuffyStudent: school = 'luffycity' def learn(self): print('is learning') def eat(self): print('is sleeping') # 查看 print(LuffyStudent.school) # luffystudent.__dict__['school'] print(LuffyStudent.learn) # Luffystudent.__dict_ ('learn') """ luffycity <function LuffyStudent.learn at 0x101cb3620> """ # 增 LuffyStudent.country = 'China' print(LuffyStudent.__dict__) print(LuffyStudent.country) """ {'__module__': '__main__', 'school': 'luffycity', 'learn': <function LuffyStudent.learn at 0x101eb3620>, 'eat': <function LuffyStudent.eat at 0x1040211e0>, '__dict__': <attribute '__dict__' of 'LuffyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'LuffyStudent' objects>, '__doc__': None, 'country': 'China'} China """ # 刪 del LuffyStudent.country # 改 LuffyStudent.school = 'whu' print(LuffyStudent.school) """ whu """
調用類(實例化),獲得程序中的對象。
class LuffyStudent: school = 'luffycity' def learn(self): print('is learning') def eat(self): print('is eating') def sleep(self): print('is sleeping') # 後產生對象 stu1 = LuffyStudent() # 不是執行類體,而是實例化 stu2 = LuffyStudent() stu3 = LuffyStudent() print(stu1) print(stu2) print(stu3) """ <__main__.LuffyStudent object at 0x10401ae80> <__main__.LuffyStudent object at 0x10401af28> <__main__.LuffyStudent object at 0x10401af60> """
實例化完成後,stu一、stu二、stu3都同樣了,這三者除了類似的屬性外還有各類不一樣的屬性,就須要用到__init__方法了。
__init__方法是在對象產生以後纔會執行,只用來爲對象進行初始化操做,能夠有任意代碼,但必定不能有返回值。
實例化後會產生對象的名稱空間,對象的名稱空間也能夠用stu1.__dict__查看:{'Name': '百合', 'Sex': '女', 'Age': 12}
class LuffyStudent: school = 'luffycity' def __init__(self, name, sex, age): # 實例化時自動調用 self.Name = name self.Sex = sex self.Age = age def learn(self): print('is learning') def eat(self): print('is sleeping') # 產生對象 stu1 = LuffyStudent('百合', '女', 12) print(stu1.Name) """ 加上__init__方法後,實例化的步驟 一、先產生一個空對象 二、LuffyStudent.__init__(stu1, '百合', '女', 12) """ # 查 print(stu1.__dict__) print(stu1.Name) print(stu1.Sex) print(stu1.Age) """ {'Name': '百合', 'Sex': '女', 'Age': 12} 百合 女 12 """ # 改 stu1.Name = '李二丫' print(stu1.__dict__) print(stu1.Name) """ {'Name': '李二丫', 'Sex': '女', 'Age': 12} 李二丫 """ # 刪除 del stu1.Name print(stu1.__dict__) """ {'Sex': '女', 'Age': 12} """ # 增 stu1.class_name = 'python開發' print(stu1.__dict__) """ {'Sex': '女', 'Age': 12, 'class_name': 'python開發'} """ stu2 = LuffyStudent('李三炮', '男', 22) print(stu2.__dict__) """ {'Name': '李三炮', 'Sex': '男', 'Age': 22} """
當類有了__init__方法後,實例化時先調用類產生空對象,再調用__init__()方法。
上述代碼中也包含有對象的使用,對對象的增刪改查操做。
self,就是實例自己!你實例化時python解釋器會自動把這個實例自己經過self參數傳進去。
self是實例化時自動將對象/實例自己傳給__init__的第一個參數,你也能夠給它起個別的名字,可是通常正常人都不會這麼作,由於改了別人就不認識了。
注意:def __init__(self): 這句話能夠寫也能夠不寫,只要有參數參進來的時候就必須得寫
def 方法名(self):這裏的self必須得寫
類中有兩種屬性:數據屬性和函數屬性。
class LuffyStudent: school = 'luffycity' def __init__(self, name, sex, age): # 實例化時自動調用 self.Name = name self.Sex = sex self.Age = age def learn(self): print('%s is learning' % self.Name) def eat(self): print('%s is sleeping' % self.Name) # 產生對象 stu1 = LuffyStudent('百合', '女', 12) stu2 = LuffyStudent('李三炮', '男', 38) stu3 = LuffyStudent('張鐵蛋', '男', 48) # 對象:特徵和技能的結合體 # 類:類是一系列對象類似的特徵與類似技能的結合體
# 類中數據屬性:是全部對象共有的(都是同樣的) print(LuffyStudent.school, id(LuffyStudent.school)) print(stu1.school, id(stu1.school)) print(stu2.school, id(stu2.school)) """內存地址同樣 luffycity 4325120112 luffycity 4325120112 luffycity 4325120112 """
# 類中函數屬性:是綁定給對象的,綁定到不一樣的對象是不一樣的綁定方法,對象調用綁定方法時,會把對象自己當作第一個參數傳入,傳給self print(LuffyStudent.learn) LuffyStudent.learn(stu1) """ <function LuffyStudent.learn at 0x1040211e0> 百合 is learning """ print(stu1.learn) print(stu2.learn) print(stu3.learn) """綁定方法,每一個人的函數內存地址不一樣 <bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x10402cc18>> <bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x10402cc50>> <bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x10402cc88>> """
優先在對象中查找,對象中沒有再在類中查找,類中沒有會去父類查找,最後都沒有則拋出異常。
# 屬性查找,優先對象中查找,對象中沒有在類中查找 # stu1.x = 'from stu1' LuffyStudent.x = 'from Luffycity class' print(stu1.__dict__) print(stu1.x) """ {'Name': '百合', 'Sex': '女', 'Age': 12} from Luffycity class """
在屬性查找那一小節中,定義了類並實例化出了三個對象stu一、stu二、stu3。
class LuffyStudent: school = 'luffycity' def __init__(self, name, sex, age): # 實例化時自動調用 self.Name = name self.Sex = sex self.Age = age def learn(self): print('%s is learning' % self.Name) def eat(self): print('%s is sleeping' % self.Name) # 產生對象 stu1 = LuffyStudent('百合', '女', 12) stu2 = LuffyStudent('李三炮', '男', 38) stu3 = LuffyStudent('張鐵蛋', '男', 48)
類中定義的函數(沒有被任何裝飾器裝飾的)是類的函數屬性,類可使用,但必須遵循函數的參數規則,有幾個參數須要傳幾個參數。
LuffyStudent.learn(stu1) LuffyStudent.learn(stu2) LuffyStudent.learn(stu3) """ 百合 is learning 李三炮 is learning 張鐵蛋 is learning """
類中定義的函數(沒有被任何裝飾器裝飾的),其實主要是給對象使用的,並且是綁定到對象的,雖然全部對象指向的都是相同的功能,可是綁定到不一樣的對象就是不一樣的綁定方法
強調:綁定到對象的方法的特殊之處在於,綁定給誰就由誰來調用,誰來調用,就會將‘誰’自己當作第一個參數傳給方法,即自動傳值(方法__init__也是同樣的道理)。
stu1.learn() stu2.learn() stu3.learn() """ 百合 is learning 李三炮 is learning 張鐵蛋 is learning """
注意:綁定到對象的方法的這種自動傳值的特徵,決定了在類中定義的函數都要默認寫一個參數self,self能夠是任意名字,可是約定俗成地寫出self。
python中一切皆爲對象,且Python3中類與類型是一個概念,類型就是類。
class student: school = 'whu' # python當中一切皆對象,在python3中統一了類和類型的概念 print(list) print(dict)∂ print(student) """ <class 'list'> <class 'dict'> <class '__main__.student'> """
以list類型舉例,類型list就是類list,對類實例化後,對象調用綁定方法append爲對象添加元素。
>>> list <class 'list'> #實例化的到3個對象l1,l2,l3 >>> l1=list() >>> l2=list() >>> l3=list() #三個對象都有綁定方法append,是相同的功能,但內存地址不一樣 >>> l1.append <built-in method append of list object at 0x10b482b48> >>> l2.append <built-in method append of list object at 0x10b482b88> >>> l3.append <built-in method append of list object at 0x10b482bc8> #操做綁定方法l1.append(3),就是在往l1添加3,絕對不會將3添加到l2或l3 >>> l1.append(3) >>> l1 [3] >>> l2 [] >>> l3 [] #調用類list.append(l3,111)等同於l3.append(111) >>> list.append(l3,111) #l3.append(111) >>> l3 [111]
class 類名: def __init__(self,參數1,參數2): self.對象的屬性1 = 參數1 self.對象的屬性2 = 參數2 def 方法名(self):pass def 方法名2(self):pass 對象名 = 類名(1,2) #對象就是實例,表明一個具體的東西 #類名() : 類名+括號就是實例化一個類,至關於調用了__init__方法 #括號裏傳參數,參數不須要傳self,其餘與init中的形參一一對應 #結果返回一個對象 對象名.對象的屬性1 #查看對象的屬性,直接用 對象名.屬性名 便可 對象名.方法名() #調用類中的方法,直接用 對象名.方法名() 便可
避免定義一大堆全局變量。
class MySQLHandler: def __init__(self,host,port,db,charset='utf8'): self.host=host self.port=port self.db=db self.charset=charset self.conn=connect(self.host,self.port,self.db,self.charset) def exc1(self,sql): return self.conn.execute(sql) def exc2(self,sql): return self.conn.call_proc(sql) obj=MySQLHandler('127.0.0.1',3306,'db1') obj.exc1('select * from tb1;') obj.exc2('存儲過程的名字')
定義類併產生多個對象
class Chinese: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex p1=Chinese('egon',18,'male') p2=Chinese('alex',38,'female') p3=Chinese('wpq',48,'female')
若是新增一個類屬性,會馬上反映給全部對象,而對象卻無需修改。
class Chinese: country='China' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def tell_info(self): info=''' 國籍:%s 姓名:%s 年齡:%s 性別:%s ''' %(self.country,self.name,self.age,self.sex) print(info) p1=Chinese('egon',18,'male') p2=Chinese('alex',38,'female') p3=Chinese('wpq',48,'female') print(p1.country) p1.tell_info()
練習1:編寫一個學生類,產生一堆學生對象。
要求:有一個計數器(屬性),統計總共實例了多少個對象
class Student: # 類名頭字母大寫 school = 'whu' count = 0 def __init__(self, name, age, sex): # 爲對象定製對象本身獨有的特徵 self.name = name self.age = age self.sex = sex # self.count += 1 # 每一個對象都是1,沒法實現累加,student類的count一直都是0 Student.count += 1 def learn(self): print('%s is learning' % self.name) def eat(self): print('%s is eating very happy!' % self.name) stu1 = Student('alex', 'male', 38) # 實例化一次就觸發一次__init__ stu2 = Student('jinxing', 'female', 48) stu3 = Student('egon', 'male', 18) print(Student.count) print(stu1.count) print(stu2.count) print(stu3.count) print(stu1.__dict__) print(stu3.__dict__) """ 3 3 3 3 {'name': 'alex', 'age': 'male', 'sex': 38} {'name': 'egon', 'age': 'male', 'sex': 18} """
練習2:模仿王者榮耀定義兩個英雄類, (10分鐘)
要求:一、英雄須要有暱稱、攻擊力、生命值等屬性;
二、實例化出兩個英雄對象;
三、英雄之間能夠互毆,被毆打的一方掉血,血量小於0則斷定爲死亡。
class Garen: camp = 'Demacia' def __init__(self, nickname, life_value, aggresivity): self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attack(self, enemy): enemy.life_value -= self.aggresivity class Riven: camp = 'Noxus' def __init__(self, nickname, life_value, aggresivity): self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attack(self, enemy): enemy.life_value -= self.aggresivity g1 = Garen('草叢倫', 100, 30) r1 = Riven('可愛的瑞雯', 80, 50) print(r1.life_value) g1.attack(r1) # 攻擊了一刀 r1.attack(g1) print(r1.life_value) print(g1.life_value)
函數:函數是封裝了一些獨立的功能,能夠直接調用,python內置了許多函數,同時能夠自建函數來使用。
方法:方法和函數相似,一樣封裝了獨立的功能,可是方法是須要經過對象來調用的,表示針對這個對象要作的操做,使用時採用點方法。