python面向對象進階-07類的封裝

什麼是類的封裝

對外隱藏內部實現細節和屬性,並提供簡易訪問的接口python

爲何要封裝

兩個目的:

1.爲了保證 關鍵數據的安全性
​2.對外部隱藏實現細節,隔離複雜度編程

【好處】

  1. 將變化隔離;
  2. 便於使用;
  3. 提升複用性;
  4. 提升安全性;

權限

python中的權限分爲兩種
1.公開 外界能夠直接訪問和修改
2.私有 外界不能直接訪問和修改,在當前類中能夠直接修改和訪問緩存

封裝的兩個層次

1.第一個層面的封裝(什麼都不用作):建立類和對象會分別建立兩者的名稱空間,咱們只能用類名.或者obj.的方式去訪問裏面的名字,這自己就是一種封裝
2.第二個層面的封裝:類中把某些屬性和方法隱藏起來(或者說定義成私有的),只在類的內部使用、外部沒法訪問,或者留下少許接口(函數)供外部訪問

封裝的使用語法

_名字 都是私有的,原則上是僅供內部調用的,外部依然能夠_名字調用(但本意爲不要調用!!!)
__名字 設置爲私有屬性或方法 實質是在加載類時候,把__替換成了 _類名__,外部能夠_類名__名字調用(但本意爲不要調用)
區別: 不一樣於_名字,這種封裝在外部單純屬性或方法名不會會被調用
ps:由於python通常不會強制要求程序必須怎麼怎麼的,
python要想與其餘編程語言同樣,嚴格控制屬性的訪問權限,只能藉助內置方法如__getattr__安全

客官,菜(code)來了-->類中對象屬性的封裝


你好socket

class Person:
    def __init__(self, id_number, name, age):
        self.__id_number = id_number
        self.name = name
        self.age = age

    def show_id(self):
        print(self.__id_number)

p = Person("1111111111111", "jack", 29)

p.__id_number = "222"
print(p.__id_number)

p.show_id()

客官,菜(code)又來了-->類中對象方法的封裝編程語言

class PC:
    def __init__(self,price,kind,color):
        self.price = price
        self.kind = kind
        self.color = color

    def open(self):
        print("接通電源")
        self.__check_device()
        print("載入內核")
        print("初始化內核")
        self.__start_services()
        print("啓動GUI")
        self.__login()


    def __check_device(self):
        print("硬件檢測1")
        print("硬件檢測2")
        print("硬件檢測3")
        print("硬件檢測4")

    def __start_services(self):
        print("啓動服務1")
        print("啓動服務2")
        print("啓動服務3")
        print("啓動服務4")

    def  __login(self):
        print("login....")
        print("login....")
        print("login....")

pc1 = PC(20000,"香蕉","黃色")
# pc1.open()

pc1.login()

類的封裝的自動變形

在python中用雙下劃線的方式實現隱藏屬性(設置成私有的)
類中全部雙下劃線開頭的名稱如__x都會自動變造成:_類名__x的形式:函數

自動變形的特色:

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

自動變形的注意點

這種機制也並無真正意義上限制咱們從外部直接訪問屬性,知道了類名和屬性名就能夠拼出名字:_類名__屬性,而後就能夠訪問了,如a._A__N
變形的過程只在類的定義時發生一次,在定義後的賦值操做,不會變形
在繼承中,父類若是不想讓子類覆蓋本身的方法,能夠將方法定義爲私有的

類的封裝-私有模塊

python並不會真的阻止你訪問私有的屬性,模塊也遵循這種約定,若是模塊中的變量名_private_module以單下劃線開頭,那麼from module import *時不能被導入該變量,可是你from module import _private_module依然是能夠導入該變量的設計

ps: 其實不少時候你去調用一個模塊的功能時會遇到單下劃線開頭的(socket._socket,sys._home,sys._clear_type_cache),這些都是私有的,原則上是供內部調用的,做爲外部的你,獨斷獨行也是能夠用的,只不過顯得稍微傻逼一點點
python要想與其餘編程語言同樣,嚴格控制屬性的訪問權限,只能藉助內置方法如__getattr__,詳見面向對象高級部分。code

訪問被隱藏的屬性:

​ 提供用於訪問和修改的方法

客官,菜(code)來了

"""
這是一個下載器類,須要提供一個緩存大小這樣的屬性
緩存大小不能超過內存限制

"""
class Downloader:
    def __init__(self,filename,url,buffer_size):
        self.filename = filename
        self.url = url
        self.__buffer_size= buffer_size

    def start_download(self):
        if self.__buffer_size <= 1024*1024:
            print("開始下載....")
            print("當前緩衝器大小",self.__buffer_size)
        else:
            print("內存炸了! ")

    def set_buffer_size(self,size):
        #能夠在方法中添加額外的邏輯
        if not type(size) == int:
            print("大哥 緩衝區大小必須是整型")
        else:
            print("緩衝區大小修改爲功!")
            self.__buffer_size = size

    def get_buffer_size(self):
        return self.__buffer_size

d = Downloader("葫蘆娃","http://www.baicu.com",1024*1024)

# 經過函數取修改內部封裝的屬性
d.set_buffer_size(1024*512)

# 經過函數訪問內部封裝的屬性
print(d.get_buffer_size())
print(d.filename)

d.start_download()

因而可知 利用好私有屬性在類內部中能夠被調用的狀況 用函數封裝好簡易的接口,而後外部經過調用它得到對應函數接口裏面執行的設計好的對私有屬性的操做結果. 這樣的方式來實現外部來訪問封裝的屬性!!

相關文章
相關標籤/搜索