1. 程式人生 > >python學習_day26_面向對象之封裝

python學習_day26_面向對象之封裝

style code 實例 rop 所有 nbsp 本質 ont 隱藏

1、私有屬性

(1)動態屬性

  在python中用雙下劃線開頭的方式將屬性隱藏起來。類中所有雙下劃線開頭的名稱,如__x都會自動變形成:_類名__x的形式。這種自動變形的特點是:

  a.類中定義的__x只能在內部使用,如self.__x,引用的就是變形的結果。b.這種變形其實正是針對外部的變形,在外部是無法通過__x這個名字訪問到的。c.在子類定義的__x不會覆蓋在父類定義的__x,因為子類中變形成了:_子類名__x,而父類中變形成了:_父類名__x,即雙下滑線開頭的屬性在繼承給子類時,子類是無法覆蓋的。

class Teacher:
    def __init__(self,name,pswd):
        self.name
=name self.__pswd=pswd #私有屬性 def func(self): print(self.__pswd) alex=Teacher(alex,3714) alex.func() # print(alex.__pswd) #私有屬性不可以通過此方式查看 print(alex._Teacher__pswd) #
私有屬性外部查看的方式:_Teacher__pswd儲存

(2)靜態屬性

  私有化的方式同樣為在屬性名前加雙下劃線,只能在內部進行使用,外部查看方式與動態屬性一樣。

class Teacher:
    __identifier=teacher                                     #私有靜態屬性
    def __init__(self,name,pwd):
        self.name=name
        self.__pwd=pwd                                         #私有屬性
    def
func(self): print(self.__pwd,Teacher.__identifier) print(Teacher._Teacher__identifier) #在外面查看靜態屬性方法 alex=Teacher(alex,1234) alex.__a=aaa #在外部定義,並不會形成私有化,__a即為一個合法的正常變量名 print(alex.__dict__) #查看動態屬性字典,結果為:{‘name‘: ‘alex‘, ‘_Teacher__pwd‘: ‘1234‘, ‘__a‘: ‘aaa‘}

問題點總結:

  (a).這種機制也並沒有真正意義上限制我們從外部直接訪問屬性,知道了類名和屬性名就可以拼出名字:_類名__屬性,然後就可以訪問了,如a._A__N。

  (b).“__屬性”變形到“_類名__屬性”只在類的內部生效,在定義後的進行的近似私有化賦值操作,不會變形,為正常的賦值過程。

2、私有方法

  私有化方法也只能在類的內部進行進行使用,有一些方法的返回值只是用來作為中間結果,可以進行私有化,如下例:

class Teacher:
    def __init__(self,name,pwd):
        self.name=name
        self.__pwd=pwd                                    #私有屬性
    def __func(self):                                     #私有方法
        return hash(self.__pwd)
    def login(self,password):
        return hash(password)==self.__func()

alex=Teacher(alex,1234)
ret=alex.login(2234)
print(ret)                                                #輸出結果為:False    

  在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義為私有的。

class Foo:
    def __jinghong_sb(self):                             #變形為:_Foo__jinghong_sb
        print(Foo)
class Son(Foo):
    def __jinghong_sb(self):                             #變形為:_Son__jinghong_sb
        print(Son)
    def func(self):
        self.__jinghong_sb()                             #變形為:_Son__jinghong_sb,

son = Son()
son.func()                                               #結果為:son

3、property方法

  實現類中的方法時,以查看類的屬性的方式進行,即將類中的方法看起來像屬性而不是方法。如下例:

#例1:
class
Person: def __init__(self,name,height,weight): self.name = name self.__height = height self.__weight = weight @property def bmi(self): return self.__weight / (self.__height**2) jinghong = Person(景弘,1.8,94) print(jinghong.name,jinghong.bmi) #輸出結果:景弘 29.012345679012345

 

#例2:
import math
class Circle:
    def __init__(self,radius): 
        self.radius=radius

    @property
    def area(self):
        return math.pi * self.radius**2               #計算面積

    @property
    def perimeter(self):
        return 2*math.pi*self.radius                  #計算周長

c=Circle(10)
print(c.radius)
print(c.area)                                         #可以向訪問數據屬性一樣去訪問area,會觸發一個函數的執行,動態計算出一個值
print(c.perimeter)                                    #可以向訪問數據屬性一樣去訪問area,會觸發一個函數的執行,動態計算出一個值

  將一個類的函數定義成特性以後,對象再去使用的時候obj.name,根本無法察覺自己的name是執行了一個函數然後計算出來的,這種特性的使用方式遵循了統一訪問的原則。以上不可以通過賦值對jinghong.bmi、c.area、c.perimeter進行更改。一個靜態屬性property本質就是實現了get,set,delete三種方法,具體實例如下:

class Shop:
    discount = 0.75
    def __init__(self,name,price):
        self.name = name
        self.__price = price
    @property          
    def price(self):
        return self.__price * Shop.discount
    @price.setter      
    def price(self,new_price):
        self.__price = new_price
    @price.deleter
    def price(self):
        del self.__price

apple = Shop(apple,5)
print(apple.price)                                   #獲取商品價格
print(apple.__dict__)                                #輸出結果:{‘name‘: ‘apple‘, ‘_Shop__price‘: 5}
apple.price = 6                                      #修改商品原價
print(apple.price)
print(apple.__dict__)                                #輸出結果:{‘name‘: ‘apple‘, ‘_Shop__price‘: 6}
del apple.price                                      #刪除商品原價
print(apple.__dict__)                                #輸出結果:{‘name‘: ‘apple‘}
  註意:只有在屬性AAA定義property後才能定義AAA.setter,AAA.deleter,如上例且各屬性方法名需一樣,均為price。
4、classmethod和staticmethod
  (1)普通方法:
必須傳一個對象 可以使用對象的屬性和類的屬性
class A:
    def __init__(self,name):
        self.name = name

    def func(self):                                 #普通方法,self為形式參數
        print( self.name)
  (2)類方法(classmethod):必須傳一個類,方法不需要使用對象的屬性,但可以使用類的屬性
class A:
    role = a
    @classmethod
    def class_method(cls):                          #類方法,cls代表類
        print(cls.role)
A.class_method()                                    #輸出結果:a類名.方法名()調用

  (3)靜態方法(staticmethod):沒有必須傳的參數,方法不需要用對象的屬性和類的屬性

class Staticmethod_Demo():
    role = dog
    @staticmethod
    def func():                                   #靜態方法,不需要參數
        print("a")
Staticmethod_Demo.func()                          #調用方式:類名.方法名()
  使用情況:不能將函數獨立的放在類外面 完全使用面向對象編程的時候,並且這個函數完全不需要依賴對象的屬性和類的屬性, 就可以用staticmethod裝飾這個函數。
 

 

 
 

python學習_day26_面向對象之封裝