1. 程式人生 > >第五章---面向對象---1.封裝之如何實現屬性的隱藏/2.封裝的意義/3.封裝與擴展性/4.property的使用

第五章---面向對象---1.封裝之如何實現屬性的隱藏/2.封裝的意義/3.封裝與擴展性/4.property的使用

bar print 意義 一個 為什麽 驗證 產生 get mod

1.封裝之如何實現屬性的隱藏

封裝: __x=1  # 把數據屬性隱藏 (如何實現隱藏)  類定義階段  __開頭發生了變形  __x --> _A__x
特點:
1.在類外部無法直接:obj.__AttrName
2.在類內部是可以直接使用:obj.__AttrName # 為什麽會這樣?python 如何實現的 !類定義階段已經變形 #__x --> _A__x #self._A_foo()
3.子類無法覆蓋父類__開頭的屬性 它兩根本不是一個名字 #_Foo__func #_Bar__func
總結:
這種變形需要註意的問題:
1.這種機制也並沒有真正意義上限制我們從外部直接訪問屬性,知道了類名和屬性名就可以拼出名字:_類名__屬性,然後就可以訪問了,如a._A__N eg:print(A._A__x)
2.變形的過程只在類的定義時發生一次,在定義後的賦值操作,不會變形 eg: b.__age=18 {‘_B__name‘: ‘alice‘, ‘__age‘: 18}
3.在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義為私有的 eg: def __foo(self): #_A__foo
  1 # class A:
  2 #     __x = 1 # 把數據屬性隱藏 _A__x = 1
  3 #
  4 #     def __init__(self,name):
  5 #         self.__name = name # self._A__name = name
  6 #
  7 #     def __foo(self): # 把函數屬性隱藏 def _A__foo(self):
  8 #         print(‘run foo‘)
  9 #
 10 #     def bar(self):
 11 #         self.__foo() # self._A__foo()  # 類內部訪問時已經變形了
12 # print(‘from bar‘) 13 # 14 # print(A.__dict__) 15 16 # {‘__module__‘: ‘__main__‘, ‘_A__x‘: 1, ‘__init__‘: <function A.__init__ at 0x0000017AC92B0B70>, ‘_A__foo‘: <function A.__foo at 0x0000017AC92B0BF8>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘A‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘A‘ objects>, ‘__doc__‘: None}
16 # 17 # 18 # print(A.__x) 19 # print(A.__foo) 20 21 # a = A(‘egon‘) 22 #print(a.__name) 23 24 # print(A.__dict__) 25 # print(a.__dict__) 26 27 # a.bar() 28 # run foo 29 # from bar 30 31 --------------------------------------------------------- 32 33 # class Foo: 34 # def func(self): 35 # print(‘from foo‘) 36 # 37 # class Bar(Foo): 38 # def func(self): 39 # print(‘from bar‘) 40 # 41 # b = Bar() 42 # b.func() 43 # # from bar 44 45 # class Foo: 46 # def __func(self): #_Foo__func 47 # print(‘from foo‘) 48 # 49 # class Bar(Foo): 50 # def __func(self): # _Bar__func 51 # print(‘from bar‘) 52 53 ------------------------------------------------------- 54 55 # class B: 56 # __x = 1 57 # 58 # def __init__(self,name): 59 # self.__name = name 60 61 # 驗證問題一: 62 # print(B._B__x) 63 64 # 驗證問題二: 65 # B.__y = 2 66 # print(B.__dict__) 67 # {‘_B__x‘: 1, ‘__y‘: 2, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘B‘ objects>, 68 # ‘__module__‘: ‘__main__‘, ‘__doc__‘: None, ‘__init__‘: <function B.__init__ at 0x023B02B8>, 69 # ‘__dict__‘: <attribute ‘__dict__‘ of ‘B‘ objects>} 70 # b = B(‘egon‘) 71 # print(b.__dict__) 72 # # {‘_B__name‘: ‘egon‘} 73 # 74 # b.__age = 18 75 # print(b.__dict__) 76 # # {‘_B__name‘: ‘egon‘, ‘__age‘: 18} 77 78 # 驗證問題三: 79 # class A: 80 # def foo(self): 81 # print(‘A.foo‘) 82 # def bar(self): 83 # print(‘A.bar‘) 84 # self.foo() # b.foo() 85 # 86 # class B(A): 87 # def foo(self): 88 # print(‘B.foo‘) 89 # 90 # b = B() 91 # b.bar() 92 93 # A.bar 94 # B.foo 95 96 class A: 97 def __foo(self): #_A_foo 98 print(A.foo) 99 def bar(self): 100 print(A.bar) 101 self.__foo() # self._A__foo() 102 103 class B(A): 104 def __foo(self): # _B__foo 105 print(B.foo) 106 107 b = B() 108 b.bar() 109 110 # A.bar 111 # A.foo

2.封裝的意義

封裝數據屬性目的:  (封裝不是單純意義上的隱藏)
明確的區分內外,控制外部對隱藏的屬性的操作行為

封裝方法屬性目的:
隔離復雜度 # a=ATM() a.withdraw()
 1 # 1.封裝數據屬性:明確的區分內外,控制外部對隱藏的屬性的操作行為
 2 # class People:
 3 #     def __init__(self,name,age):
 4 #         self.__name = name
 5 #         self.__age = age
 6 #
 7 #     def tell_info(self):
 8 #         print(‘Name:<%s> Age:<%s>‘ % (self.__name,self.__age))
 9 #
10 #     def set_info(self,name,age):
11 #         if not isinstance(name,str):
12 #             print(‘名字必須是字符串類型‘)
13 #             return
14 #         if not isinstance(age,int):
15 #             print(‘年齡必須是數字類型‘)
16 #             return
17 #         self.__name = name
18 #         self.__age = age
19 # p = People(‘egon‘,18)
20 # p.tell_info()
21 # # p.set_info(‘EGON‘,38)
22 # p.set_info(‘EGON‘,‘18‘)
23 # p.tell_info()
24 
25 # 2.封裝方法的目的:隔離復雜度
26 
27 class ATM:
28     def __card(self):
29         print(插卡)
30     def __auth(self):
31         print(用戶認證)
32     def __input(self):
33         print(輸入取款金額)
34     def __print_bill(self):
35         print(打印賬單)
36     def __take_money(self):
37         print(取款)
38 
39     def withdraw(self):
40         self.__card()
41         self.__auth()
42         self.__input()
43         self.__print_bill()
44         self.__take_money()
45 
46 a=ATM()
47 a.withdraw()

3.封裝與擴展性

面向對象:可擴展性高
面向對象三大特性:繼承 多態 封裝
封裝的擴展性:
def tell_area(self): # 對使用者來說 不用改變 方式 開發者在類裏面修改
class Room:
    def __init__(self,name,owner,weight,length):
        self.name = name
        self.owner = owner

        self.__weight = weight
        self.__length = length

    def tell_area(self): # 對使用者來說 不用改變方式
        return self.__weight * self.__length

r = Room(衛生間,alex,10,10)

print(r.tell_area())

4.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.86
-------------------------------
property :
@property
def bmi(self): 必須有個返回值
print(p.bmi) 可以使 函數屬性 偽裝成 數據屬性 bmi 是名詞

p.bmi=23 # 不能賦值 can‘t set attribute bmi 實質是個方法

總結:通過計算得來的方法 可以通過@property 偽裝成數據屬性
@property 查看 必須有返回值
@name.setter 修改
@name.deleter 刪除
 1 # class People:
 2 #     def __init__(self,name,weight,height):
 3 #         self.name=name
 4 #         self.weight=weight
 5 #         self.height=height
 6 #
 7 #     @property
 8 #     def bmi(self):  # 必須要有個返回值
 9 #         return self.weight / (self.height ** 2)
10 #
11 # p=People(‘egon‘,75,1.81)
12 # p.bmi=p.weight / (p.height ** 2)
13 # print(p.bmi)
14 
15 # print(p.bmi())  # 函數 是 去做什麽! 是動詞  對於使用者 產生誤解 調了一個動詞
16 
17 # print(p.bmi)      # 使用者可以像 訪問數據屬性 那樣 訪問 函數屬性
18 # p.height=1.82
19 # print(p.bmi)
20 # p.bmi=33  # 不能賦值 can‘t set attribute  bmi 實質是個方法
21 
22 # ------------------------------------------------------------
23 class People:
24     def __init__(self,name):
25         self.__name=name
26 
27     @property     # 查看
28     def name(self):
29         # print(‘getter‘)
30         return self.__name
31 
32     @name.setter  # 修改  # 前提是 一定被裝飾過 property
33     def name(self,val):
34         # print(‘setter‘,val)
35         if not isinstance(val,str):
36             print(名字必須是字符串)
37             return
38         self.__name=val
39 
40     @name.deleter  # 刪除
41     def name(self):
42         # print(‘deleter‘)
43         print(不允許刪除)
44 
45 
46 p=People(alice)
47 # print(p.name)
48 
49 # p.name=‘alex‘
50 # print(p.name)
51 
52 del p.name

  

第五章---面向對象---1.封裝之如何實現屬性的隱藏/2.封裝的意義/3.封裝與擴展性/4.property的使用