面向對象的成員與嵌套
成員:
一.變量
變量包括:實例變量(字段)和類變量(靜態字段),在定義和使用中有區別,本質區別是內存中保存的位置不同.(實例變量保存在對象中,類變量保存在類中.)
class Provice: country = ‘中國‘ #類變量 def __init__(self, name): self.name = name #實例變量 # 訪問實例變量,通過對象 obj = Provice(‘北京市‘) print(obj.name) #訪問類變量,通過類 print(Provice.country) 結果: 北京市 中國
實例變量與類變量的內存位置:
類變量在內存中只保存一份
實例變量在每個對象中都保存一份
應用場景: 通過類創建對象時,如果每個對象都具有相同的字段,那麽就使用靜態字段.
二.方法
方法包括:普通方法,靜態方法,類方法.三種方法在內存中都在類中,區別在於定義和調用方式不同.
普通方法: 由對象調用,至少有一個self參數,執行普通方法時,自動調用該方法的對象賦值給self.
靜態方法: 由類調用,定義時在方法上面寫@staticmethod,無默認參數.
類方法: 由類調用,定義時在方法上面寫@classmethod,至少有一個cls參數,執行類方法時,自動調用該方法的類復制給cls.
class Foo: def func(self): #至少有一個self參數 print(‘普通方法‘) @classmethod def func1(cls): #至少有一個cls參數 print(‘類方法‘) @staticmethod def func2(): #可以沒有參數 print(‘靜態方法‘) obj = Foo() #實例化一個對象 obj.func() #通過對象調用普通方法 obj.func1() #可以通過對象調用類方法,一般不建議用 obj.func2() #可以通過對象調用靜態方法,一般不建議用 Foo.func1() #通過類調用類方法 Foo.func2() #通過類調用靜態方法 結果: 普通方法 類方法 靜態方法 類方法 靜態方法
相同點: 所有的方法,都屬於類中,在內存中只保存一份.
不同點: 方法的定義不同,調用時自動傳入的參數不同.
靜態方法的使用: 如果方法無需使用對象中封裝的值,就可以使用靜態方法.
三.屬性
屬性是普通方法的變種
class Foo:
def func(self):
print(‘普通方法‘)
@property #定義屬性時,方法上面加@property
def func1(self): #屬性定義時,只有一個self參數,不能加參數
return ‘屬性‘
obj = Foo()
obj.func() #普通方法調用時,需要加括號
ret = obj.func1 #屬性調用時,無需加括號
print(ret)
結果:
普通方法
屬性
屬性存在的意義是調用的時候不需要加括號.
屬性的應用場景: 類中的方法,既不需要傳參數且有返回結果.可以使用@property.
類的成員修飾符
每一個類的成員都有兩種形式: 公有成員, 私有成員
公有成員: 在任何地方都能訪問
私有成員:只有在類的內部可以訪問
公有成員與私有成員的定義不同:私有成員命名時,前兩個字符是下劃線.(__init__等特殊成員除外)
class Foo: def __init__(self): self.name = ‘公有字段‘ self.__foo = ‘私有字段‘ def per(self): print(self.__foo) obj = Foo() print(obj.name) obj.per() print(obj.__foo) 結果: 公有字段 私有字段 報錯
公有成員與私有成員的訪問限制不同:
字段:
公有字段:對象可以訪問,類內部可以訪問,派生類也可以訪問.
私有字段:只有類內部可以訪問.
class Foo: def __init__(self): self.foo = ‘公有字段‘ def func(self): print(self.foo) #類內部訪問 class Foo1(Foo): def show(self): print(self.foo) #派生類訪問 obj = Foo() print(obj.foo) #通過對象訪問 obj.func() #類內部訪問 obj1 = Foo1() obj1.show() #派生類訪問 結果: 公有字段 公有字段 公有字段公有字段
class Foo: def __init__(self): self.__foo = ‘私有字段‘ def func(self): print(self.__foo) #類內部訪問 class Foo1(Foo): def show(self): print(self.__foo) #派生類訪問 def per(self): self.func() obj = Foo() obj.func() #類內部訪問==>正確 # print(obj.__foo) #通過對象訪問==>錯誤 obj1 = Foo1() # obj1.show() #派生類訪問==>錯誤 obj1.per() #派生類通過基類內部訪問==>正確. #實質是通過類內部訪問私有字段
靜態字段:
公有靜態字段:類可以訪問,類內部可以訪問,派生類可以訪問
私有靜態字段:只有類內部可以訪問.
class Foo: name = ‘公有靜態字段‘ def func(self): print(Foo.name) class Foo1(Foo): def show(self): print(Foo.name) print(Foo.name) #類訪問 obj = Foo() obj.func() #類內部可以訪問 obj1 = Foo1() obj1.show() #派生類中可以訪問 結果: 公有靜態字段 公有靜態字段 公有靜態字段公有靜態字段
class Foo: __name = ‘私有靜態字段‘ def func(self): print(Foo.__name) class Foo1(Foo): def show(self): print(Foo.__name) def per(self): self.func() print(Foo.__name) #類訪問==>錯誤 obj = Foo() obj.func() #類內部訪問==>正確 obj1 = Foo1() obj1.show() #派生類中訪問==>錯誤 obj1.func() #派生類通過基類內部訪問==>正確私有靜態字段
方法,屬性的成員修飾符與上述方式相似.私有成員只能在類內部使用.
註意:如果非要訪問私有屬性,可以通過對象._類__屬性名
面向對象的成員與嵌套