面向對象之類的成員
細分類的組成成員
類大致分為兩塊區域:
第一部分:靜態字段
第二部分:動態方法
class Animal:type_name = "動物類" # 靜態變量(靜態字段)__feature = "活的" # 私有靜態變量(靜態字段)def __init__(self,name,size): # 特殊方法self.name = name # 對象屬性self.__size = size # 私有對象屬性(私有普通字段)def func1(self): # 普通方法passdef __func(self): # 私有方法print(666)@classmethod # 類方法def class_func(cls):print("類方法")@staticmethod # 靜態方法def static_func():print("靜態方法")@property # 屬性def prop(self):pass
類的私有成員
對于每一個類的成員而言都有兩種形式:
? 公有成員,在任何地方都能訪問
? 私有成員,只有在類的內部才能訪問
私有成員和公有成員的訪問限制不同:
靜態字段(靜態屬性)
? 公有靜態字段:類可以訪問;類內部可以訪問;派生類中可以訪問
? 私有靜態字段:僅類內部可以訪問
class C:name = "公有靜態字段"def func(self):print(C.name)
class D:def show(self):print(C.name)C.name #類訪問obj = C()
obj.func() # 類內部可以訪問obj_son = D()
obj_son.show() # 派生類中可以訪問
class C:__name = "私有靜態字段"def func(self):print(C.__name)
class D(C):def show(self):print(C.__name)
C.__name # 不可在外部訪問
obj = C()
obj.__name # 不可在外部訪問
obj.func() # 類內部可以訪問 obj_son = D()
obj_son.show() #不可在派生類中可以訪問
普通字段(對象屬性)
公有普通字段:對象中可以訪問;類內部可以訪問;派生類中可以訪問
私有普通字段:僅類內部可以訪問;
class C:def __init__(self):self.foo = "公有字段"def func(self):print(self.foo) # 類內部訪問class D(C):def show(self):print(self.foo) # 派生類中訪問obj = C()obj.foo # 通過對象訪問
obj.func() # 類內部訪問obj_son = D();
obj_son.show() # 派生類中訪問
class C:def __init__(self):self.__foo = "私有字段"def func(self):print(self.foo) # 類內部訪問class D(C):def show(self):print(self.foo) # 派生類中訪問obj = C()obj.__foo # 通過對象訪問 ==> 錯誤
obj.func() # 類內部訪問 ==> 正確obj_son = D();
obj_son.show() # 派生類中訪問 ==> 錯誤
方法:
- 公有方法:對象可以訪問;類內部可以訪問;派生類中可以訪問
- 私有方法:僅類內部可以訪問;
class C:def __init__(self):passdef add(self):print('in C')class D(C):def show(self):print('in D')def func(self):self.show()
obj = D()
obj.show() # 通過對象訪問
obj.func() # 類內部訪問
obj.add() # 派生類中訪問
class C:def __init__(self):passdef __add(self):print('in C')class D(C):def __show(self):print('in D')def func(self):self.__show()
obj = D()
obj.__show() # 通過不能對象訪問
obj.func() # 類內部可以訪問
obj.__add() # 派生類中不能訪問
總結:
對于這些私有成員來說,他們只能在類的內部使用,不能再類的外部以及派生類中使用.
*補充:非要訪問私有成員的話,可以通過 對象._類__屬性名,但是絕對不允許!!!*
*為什么可以通過._類__私有成員名訪問呢?因為類在創建時,如果遇到了私有成員(包括私有靜態字段,私有普通字段,私有方法)它會將其保存在內存時自動在前面加上_類名.*
類的其他成員
這里的其他成員主要就是類方法:
方法包括:普通方法、靜態方法和類方法,三種方法在內存中都歸屬于類,區別在于調用方式不同。
實例方法
? 定義:第一個參數必須是實例對象,該參數名一般約定為“self”,通過它來傳遞實例的屬性和方法(也可以傳類的屬性和方法);
? 調用:只能由實例對象調用。
類方法
? 定義:使用裝飾器@classmethod。第一個參數必須是當前類對象,該參數名一般約定為“cls”,通過它來傳遞類的屬性和方法(不能傳實例的屬性和方法);
? 調用:實例對象和類對象都可以調用。
class Student:count = 0def __init__(self,name,age):self.name = nameself.age = ageStudent.cls_func()@classmethoddef cls_func(cls):cls.count = cls.count + 1@classmethoddef getnum(cls):return cls.count
a = Student('alex',18)
b = Student('bill',20)
print(Student.getnum())
# 結果:2
類方法的兩個作用:
1.得到類名實例化對象,
2.可以操作類的屬性.
靜態方法
? 定義:使用裝飾器@staticmethod。參數隨意,沒有“self”和“cls”參數,但是方法體中不能使用類或實例的任何屬性和方法;
? 調用:實例對象和類對象都可以調用。
? 靜態方法是個獨立的、單純的函數,它僅僅托管于某個類的名稱空間中,便于使用和維護。
雙下方法
屬性:
什么是屬性property
property是一種特殊的屬性,訪問它時會執行一段功能(函數)然后返回值
例一:BMI指數(bmi是計算而來的,但很明顯它聽起來像是一個屬性而非方法,如果我們將其做成一個屬性,更便于理解)成人的BMI數值:
過輕:低于18.5
正常:18.5-23.9
過重:24-27
肥胖:28-32
非常肥胖, 高于32體質指數(BMI)=體重(kg)÷身高^2(m)EX:70kg÷(1.75×1.75)=22.86class People:def __init__(self,name,weight,height):self.name=nameself.weight=weightself.height=height@propertydef bmi(self):return self.weight / (self.height**2)p1=People('egon',75,1.85)
print(p1.bmi)
為什么要用property
將一個類的函數定義成特性以后,對象再去使用的時候obj.name,根本無法察覺自己的name是執行了一個函數然后計算出來的,這種特性的使用方式遵循了統一訪問的原則
由于新式類中具有三種訪問方式,我們可以根據他們幾個屬性的訪問特點,分別將三個方法定義為對同一個屬性:獲取、修改、刪除
class Foo:@propertydef AAA(self):print('get的時候運行我啊')@AAA.setterdef AAA(self,value):print('set的時候運行我啊')@AAA.deleterdef AAA(self):print('delete的時候運行我啊')#只有在屬性AAA定義property后才能定義AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA或者:
class Foo:def get_AAA(self):print('get的時候運行我啊')def set_AAA(self,value):print('set的時候運行我啊')def delete_AAA(self):print('delete的時候運行我啊')AAA=property(get_AAA,set_AAA,delete_AAA) #內置property三個參數與get,set,delete一一對應f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
isinstance與issubclass
class A:passclass B(A):passobj = B()print(isinstance(obj,B))
print(isinstance(obj,A))
isinstance(a,b):判斷a是否是b類(或者b類的派生類)實例化的對象
class A:passclass B(A):passclass C(B):passprint(issubclass(B,A))
print(issubclass(C,A))
issubclass(a,b): 判斷a類是否是b類(或者b的派生類)的派生類