亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python面向對象特性 - 封裝

發布時間:2020-03-31 23:01:19 來源:網絡 閱讀:668 作者:LJ_baby 欄目:編程語言

類中的私有屬性

私有屬性包括私有變量和私有方法,在 Python 中,在變量名或者方法名前面加上雙下劃線,這個屬性就成為了類的私有屬性。
?

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def __fun(self): 
        print(self.__class__)

    def say(self):
        self.__fun()       # 自動轉換為 調用 _Person__fun 方法
        print(self.__name + ' ' + str(self.__age))   # 自動轉換為 調用 \_Person\_\_name 和 \_Person\_\_age 屬性~

p = Person('Kitty', 18)
p.say()

# 輸出結果:
Kitty 18

上述示例中,__name 和 __age 為類的私有變量,私有變量僅能在類中進行訪問,在類的外部訪問不到。

p = Person('Kitty', 18)
print(p.__name)

# 報錯信息:
AttributeError: 'Person' object has no attribute '__name'

?
其實在類中定義私有屬性時,__name 和 __age 已經自動變形為 _Person__name 和 _Person__age,__fun 自動變形為 _Person__fun,即私有屬性會自動變形為_類名__屬性~

p = Person('Kitty', 18)
print(p.__dict__)

# 輸出結果:
{'_Person__name': 'Kitty', '_Person__age': 18}

?
當在類的內部通過屬性名稱訪問私有屬性時,會自動進行轉換,例如 self.__name 轉換為 self._Person__name,在類的外部不會進行這樣的自動轉換~
?
類的私有屬性只是在語法上做了訪問限制,但是并沒有真正限制從外部的訪問。在外部不能通過 對象.__屬性 來進行訪問,但是可以通過變形后的屬性名來進行訪問~

p = Person('Kitty', 18)
# print(p.__name)      # 不能這樣訪問
print(p._Person__name)
p._Person__fun()

# 結果輸出:
Kitty
<class '__main__.Person'>

對私有屬性的訪問限制只是一種規范,在開發過程中一般不允許在外部通過這種方式訪問私有屬性~
?
私有屬性的變形只在類的內部生效,在定義后的賦值操作,不會變形~

p = Person('Kitty', 18)
p.__name = 'abc'
print(p.__dict__)
print(p.__name)     # 調用的是 __name 屬性,不是私有屬性

# 輸出結果:
{'_Person__name': 'Kitty', '_Person__age': 18, '__name': 'abc'}   # 這個屬性就叫 __name
abc

?
在子類中定義的私有屬性若是和父類中的私有屬性同名,不會覆蓋父類的這些私有屬性,因為這些私有屬性變形后的名稱不同,子類:_子類名__屬性,父類:_父類名__屬性~

class Fu:
    __key = 123    # 靜態私有屬性

    def __init__(self, name):
        self.__name = name

class Zi(Fu):
    def get_name(self):
        print(self.__name)    # 變形為 self._Zi__name

    def get_key(self):
        print(Fu.__key)     # 變形為 self._Zi__key

zi = Zi('hello')
zi.get_name()     # 報錯信息:AttributeError: 'Zi' object has no attribute '_Zi__name'
zi.get_key()     # 報錯信息:AttributeError: type object 'Fu' has no attribute '_Zi__key'

?
若是父類中定義的方法不想被子類調用到,可以將方法定義為私有方法~

class A:
    def __fun(self): # 在定義時就變形為_A__fun
        print('from A')
    def test(self):
        self.__fun() # 變形為 self._A__fun(),即以當前的類為準

class B(A):
    def __fun(self):
        print('from B')

b=B()
b.test()    # 調用 A類中的test方法,test方法中的 self.__fun() 調用的是 A類中的私有方法__fun()

# 輸出結果:
from A

?
封裝的優勢在于將類內部的實現細節隱藏起來,調用者無需了解,直接調用對應的方法即可(方法名,參數都不改變),若功能需要改變,只需要在類的內部進行調整,外部的調用代碼無需改變~

property屬性

property為內置裝飾器函數,只在面向對象中使用。@property裝飾器 可以將 對方法的調用轉為 對變量的調用。示例如下:

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def name(self):
        return self.__name

    @property
    def age(self):
        return self.__age

p = Person('Kitty', 18)
print(p.name)
print(p.age)

# 結果輸出:
Kitty
18

p.name 和 p.age 其實是執行了一個函數,然后將結果返回。這種特性的使用方式遵循了統一訪問的原則。
?
p.屬性 的這個過程也可以做一些運算操作然后將結果返回~

class Room:
    def __init__(self, width, length, high):
        self.__width = width
        self.__length = length
        self.__high = high
    def area(self):
        return self.__width * self.__length * self.__high

room = Room(1, 2, 3)
print(room.area())      # 6

除了 @property,還有 @屬性.setter@屬性.deleter,要注意的是,定義了 property 后才能定義 屬性.setter,屬性.deleter ~

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, value):
        if not isinstance(value, str):  # 在設定值之前進行類型檢查
            raise TypeError('%s must be str' %value)
        self.__name = value

    @name.deleter
    def name(self):
        raise TypeError('Can not delete')

    @property
    def age(self):
        return self.__age

p = Person('Kitty', 18)
p.name = 'nihao'
print(p.name)
del p.name   # TypeError: Can not delete

說明:
執行 p.name 的時候,調用 @name.setter 修飾的方法,這樣的賦值方式在真正的賦值之前可以做一些類型檢驗的操作,或者別的自定義操作,更具靈活性~
執行 del p.name 的時候,調用 @name.deleter 修飾的方法
?
在使用 @property,@屬性.setter 和 @屬性.deleter 的時候,這幾個地方必須保持一致,即屬性名稱需要保持一致。
Python面向對象特性 - 封裝

上述示例也可以通過如下方式實現:

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def get_name(self):
        return self.__name

    def set_name(self, value):
        if not isinstance(value, str):  # 在設定值之前進行類型檢查
            raise TypeError('%s must be str' %value)
        self.__name = value

    def del_name(self):
        print('delete name')

    name = property(get_name, set_name, del_name)

    @property
    def age(self):
        return self.__age

Tip:

  • 使用 property 修飾的方法,除了 self 不能有別的參數,@屬性.deleter也一樣;
  • 使用 @屬性.setter 修飾的方法除了self 以外只能有一個參數~

.................^_^

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

壤塘县| 莱西市| 建宁县| 郴州市| 定西市| 公安县| 调兵山市| 崇明县| 丹寨县| 饶河县| 金沙县| 阳春市| 马公市| 图们市| 鸡东县| 无为县| 江津市| 民乐县| 霸州市| 大余县| 陆河县| 兴仁县| 盐池县| 夹江县| 六枝特区| 马龙县| 玉林市| 海口市| 宜城市| 运城市| 湘西| 桑植县| 安达市| SHOW| 晴隆县| 扶沟县| 河西区| 梅州市| 江华| 枣庄市| 成武县|