一切皆對象,類也是對象,類來自於元類type,如果一個類沒有聲明自己的元類,默認它就是元類。
即類是元類的實例,通過type(類)會顯示type,而實例來自於類。
類有兩個屬性,數據屬性和函數屬性,下面是一個創建類和實例化對象的例子
class animal: 'This is class for animal' #類的說明 type='animal' def __init__(self,name,sex,leg): self.name = name self.sex = sex self.leg = leg def eat(self,food): print('%s likes to eat %s'%(self.name,food)) def play(self): print('%s is playing'%self.name) print(animal.__name__)#打印類的名稱 print(animal.__doc__) #打印類的說明,__doc__屬性不能繼承給子類 print(animal.__dict__) #打印類的屬性字典 cat=animal('cat','male',4) print(cat.__dict__) #打印類的屬性字典 print(cat.type) cat.eat('mouse') cat.play() #執行結果 # animal # This is class for animal # {'__module__': '__main__', '__doc__': 'This is class for animal', 'haveTeeth': True, '__init__': <function animal.__init__ at 0x00000000021AA598>, 'eat': <function animal.eat at 0x00000000021AA620>, '__dict__': <attribute '__dict__' of 'animal' objects>, '__weakref__': <attribute '__weakref__' of 'animal' objects>} # {'name': 'cat', 'sex': 'male', 'leg': 4} # cat likes to eat mouse # animal
在class animal:范圍下面的都是對animal類的定義,其中def __init__()是定義animal類的數據屬性,__init__()不應該有返回值,否則會報錯,其他函數則是animal類的函數屬性,可以看到類下面的函數的第一個參數都是self。
當執行cat=animal('cat','male',4),觸發animal類的__init__()函數生成一個cat實例。
__dict__表示屬性字典,以字典形式存放,通過打印animal.__dict__和cat.__dict__可以發現,類有數據屬性和函數屬性,而實例只有數據屬性沒有函數屬性,但是實例可以繼承和調用對象的函數屬性。
實例調用類的函數時,會自動將實例本身作為第一個參數傳給函數,但是類自己調用函數時不會自動將實例本身作為參數傳入,例如要通過類調用play()函數,則animal.play(cat)。
類的屬性字典是共用的,而實例的屬性字典是私有的。
類屬性的查看、增加、修改和刪除
#查看類的數據屬性 print(animal.type) #修改類的數據屬性 animal.type='Animal' print(animal.type) #增加類的數據屬性 animal.haveteeth=True print(cat.haveteeth) #刪除類的數據屬性 del animal.haveteeth #增加類的函數屬性,修改類似 def play_bal(self,ball): print('The %s is playing %s'%(self.name,ball)) animal.play_ball=play_bal cat.play_ball('tennis')
實例屬性的增加
#增加實例的數據屬性,cat.__dict__['key']='value'也可以增加數據屬性但不建議使用 cat.living='land' print(cat.__dict__) #{'name': 'cat', 'sex': 'male', 'leg': 4, 'living': 'land'} #刪除實例的數據屬性 del cat.living print(cat.__dict__) #{'name': 'cat', 'sex': 'male', 'leg': 4} #修改實例的數據屬性 cat.sex='female' print(cat.sex) #female #增加實例的函數屬性 def test(): print('hello') cat.test=test cat.test() #hello
對於實例增加的函數屬性,實例在調用時不會自動將自身作為參數傳入。
需要注意的是:
如果在類前面定義了與類的數據屬性同名的全局變量,那么只要不通過類或者實例+.調用這個變量,這個變量就是指類前面定義的全局變量
如果實例增加了與類的數據屬性同名的屬性,相當於給實例增加了這個屬性,對類的屬性沒有影響。
type='mouse' class animal: type='animal' l=['a','b'] def __init__(self,name): self.name = name print(type) #此處的type是指全局變量,而不是類內部的數據屬性變量 cat=animal('cat') cat.type='male' #相當於給cat增加了一個數據屬性type,對類的type屬性沒有影響 print(cat.__dict__) print(cat.type) cat.l.append('c')#此處修改的是類的數據屬性l,與通過=賦值(給實例增加屬性)不同
__class__:實例來自哪個類
__module__:實例來自哪個模塊
類的組合
即在類實例化時,將另一個類的實例作為參數傳入,這樣可以將兩個實例關聯起來。
當類之間有顯著不同,並且較小的類是較大的類所需要的組件時,用組合比較好。
例如,描述一個機器人類,這個大類是由很多互不相關的小類組成,如機械胳膊類、腿類、電池類等。
當類之間有很多相同的屬性,提取這些統統的屬性做成基類,用繼承比較好。

class course: def __init__(self,name,price,period,teacher): self.name=name self.price=price self.period=period self.teacher=teacher class teacher: def __init__(self,name,sex): self.name=name self.sex=sex class student: def __init__(self,name,age,course): self.name=name self.age=age self.course=course t1=teacher('Bob',38) t2=teacher('Jack',45) t3=teacher('Jane',45) c1=course('python',6000,'3 months',t2)#將teacher作為參數傳遞給課程實例 c2=course('linux',7000,'5 months',t1) c3=course('mysql',6500,'5 months',t3) d={'1':c1,'2':c2,'3':c3} name='Alice' age=21 while True: choice=input('please choice course:') if choice in d.keys(): s1=student(name,age,d[choice])#將課程實例作為參數傳遞給學生實例 print(s1.__dict__) print('%s choose course %s,%s is the teacher'%(s1.name,s1.course.name,s1.course.teacher.name)) elif int(choice)==0: exit(0) else: print('please input correct choice')
運行結果如下圖