不間斷 Python 挑戰 Day 22 - 物件導向程式設計:封裝 (Encapsulation)

更新於 2022/03/02閱讀時間約 9 分鐘
類別一節中,我們可以用Student類別的實體來存取類別中的name變數、score字典、以及其中的所有方法,這些可以被類別以外的程式碼所直接存取的屬性稱為公有屬性(public attribute)、可以被類別以外的程式碼所直接呼叫的方法稱為公有方法(public method)。事實上,有時我們不希望所有類別內部實作的細節被外部知道,一方面我們希望可以把類別當作一個「黑盒子」,把一個功能單位包裝起來,僅透過統一的介面被外部取用,以方便維護;另一方面我們也不希望外部的程式碼可以隨意修改類別內部的屬性或呼叫方法,導致類別資料或運算邏輯的錯誤。
Python提供物件導向程式設計的另一個特色是封裝,利用封裝的概念,我們可以設計僅供類別內部引用的私有屬性(private attribute)與私有方法(private method),可一定程度防止此類的屬性與方法被外部程式碼輕易地誤用。

私有屬性

將類別中的屬性改為私有屬性的方法是在屬性名稱前面加上雙底線「__」,我們改寫在類別一節中的Student類別,將name與score屬性改為私有屬性。
class Student:
  # 初始化
  def __init__(self, name):
    # 私有屬性
    self.__name = name
    self.__score = {"Math": 0, "Physics": 0, "Chemistry": 0}
# 建立物件
student = Student("Jack")
# 嘗試存取私有屬性
print(student.__name)
此時,若我們想從外部直接存取私有屬性student.__name與student.__score便會發生錯誤。
Traceback (most recent call last):
  File "C:\Users\wjweng\PycharmProjects\marathon_python\venv\marathon_python_day22.py", line 32, in <module>
    print(student.__name)
AttributeError: 'Student' object has no attribute '__name'
要存取私有屬性有以下幾種方式:
  • 使用公有方法設定或回傳:在類別的內部新增方法設定或回傳私有屬性。
# 回傳名字
def get_name(self):
  return self.__name
# 設定名字
def set_name(self, name):
  self.__name = name
使用方式:
# 設定名字為Rose
student.set_name("Rose")
# 印出名字
print(student.get_name())
  • 使用property()方法設定或回傳:利用上述的公有方法搭配property()方法建立新屬性,可藉由此新屬性來設定或回傳私有屬性。
# 回傳名字
def get_name(self):
  return self.__name
# 設定名字
def set_name(self, name):
  self.__name = name
name = property(get_name, set_name)
使用方式:
# 設定名字為Jack
student.name = "Jack"
# 印出名字
print(student.name)
  • 將get_name()與set_name()方法改為相同的名稱name(),使用裝飾器@property將name()轉換為可讀取的屬性、使用裝飾器@name.setter來設定名字。
@property
def name(self):
  return self.__name
@name.setter
def name(self, name):
  self.__name = name
使用方式:
# 設定名字為Jack
student.name = "Jack"
# 印出名字
print(student.name)
然而,這個__name屬性到哪裡去了呢?我們可以用物件的__dict__屬性來看一下,__dict__是用來儲存物件屬性的一個字典,其鍵為屬性名、值為屬性的值。
print(student.__dict__)
可以看到這個私有屬性還在,只是被改名為_Student__name。
{'_Student__name': 'Jack', '_Student__score': {'Math': 0, 'Physics': 0, 'Chemistry': 0}}
因此,我們還是可以透過此名稱來存取私有屬性,但至少可以防止私有屬性被外部程式碼意外地存取或修改。
print(student._Student__name)
執行結果:
Jack

私有方法

將類別中的方法改為私有方法的方式和私有屬性相同,是在方法的名稱前面加上雙底線「__」,延續上方的範例,我們將原有的add_subject方法改為私有方法__add_subject,並在set_score方法中呼叫它。
class Student:
  # 初始化
  def __init__(self, name):
    # 私有屬性
    self.__name = name
    self.__score = {"Math": 0, "Physics": 0, "Chemistry": 0}
  # 私有方法
  def __add_subject(self, subject):
    self.__score[subject] = 0
  # 公有方法
  def set_score(self, subject, score):
    if subject not in self.__score:
      self.__add_subject(subject)
    self.__score[subject] = score
  def get_subject(self):
    for key in self.__score:
      print(key)
# 建立物件
student = Student("Jack")
# 新增科目
student.__add_subject("Art")
此時,若我們想從外部直接呼叫__add_subject方法便會發生錯誤。
Traceback (most recent call last):
  File "C:\Users\wjweng\PycharmProjects\marathon_python\venv\marathon_python_day22.py", line 40, in <module>
    student.__add_subject("Art")
AttributeError: 'Student' object has no attribute '__add_subject'
透過set_score方法,我們可以在類別內部呼叫__add_subject方法。
# 登錄分數
student.set_score("Art", 80)
# 取得分數
student.get_score("Art")
執行結果:
80
然而,和私有屬性同樣的方式,我們依然可以透過被改名後的方法名稱,從外部直接呼叫私有方法。
# 呼叫私有方法
student._Student__add_subject("Music")
# 取得現有科目
student.get_subject()
執行結果:
Math
Physics
Chemistry
Art
Music

程式範例

為什麼會看到廣告
avatar-img
47會員
36內容數
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Wei-Jie Weng的沙龍 的其他內容
大型程式的開發通常不會由一個人獨力完成,而是將程式依功能拆分成不同的函數或是類別,由不同人協力開發成各個模組,最後再將這些模組導入主程式,或是直接套用現有的模組。模組依來源可以分成三大類: Python內建的模組 外部模組,需從第三方的軟體儲存庫(如PyPI)並安裝使用 程式開發者自行開發的模組
全球公衛教授和公共教育家漢斯.羅斯林(Hans Rosling)在其著名的暢銷書「真確」中,提出了13個關於全球貧富、人口、出生/死亡率、教育、公衛等的「留意認知落差測驗」,回答的人不乏受過良好教育的專業人士,結果顯示,受測者在前12題平均只答對2題,遠不如隨機亂選的黑猩猩(如果黑猩猩會回答問題的話
到目前為止,我們所學習的都是程序性的程式設計(procedural programming),也就是程式碼是透過一連串的指令組成的程序或函數,由上而下依序執行不同的程序或是呼叫函數來完成程式的功能。 Python其實是一種物件導向的程式(object oriented programming, 簡稱
Python提供集合做為其資料結構,它就如同高中數學所學集合的概念,集合的內容一般來說是具有某種特性的事物的整體,例如考試分數及格的群體、數字1到100內的所有奇數、球箱內所有球的顏色等。因此,在一個集合中,每個元素的地位都是相同且無序,並且只能出現一次,集合和集合之間,也可以進行交集、聯集、差集等
Python依據變數有效的範圍可以區分為全域變數(Global variable)或區域變數(Local variable)。在函數內宣告的變數為區域變數,有效範圍只有在函數內,函數外部無法引用這個變數;在函數以外宣告的變數為全域變數,它的有效範圍為整個檔案,並且在函數內部也可以引用這個變數。
這篇文章將利用之前所學過的一些東西,包括if敘述、串列、while迴圈、函數等等的觀念,來實作一個撲克牌的小遊戲-21點。
大型程式的開發通常不會由一個人獨力完成,而是將程式依功能拆分成不同的函數或是類別,由不同人協力開發成各個模組,最後再將這些模組導入主程式,或是直接套用現有的模組。模組依來源可以分成三大類: Python內建的模組 外部模組,需從第三方的軟體儲存庫(如PyPI)並安裝使用 程式開發者自行開發的模組
全球公衛教授和公共教育家漢斯.羅斯林(Hans Rosling)在其著名的暢銷書「真確」中,提出了13個關於全球貧富、人口、出生/死亡率、教育、公衛等的「留意認知落差測驗」,回答的人不乏受過良好教育的專業人士,結果顯示,受測者在前12題平均只答對2題,遠不如隨機亂選的黑猩猩(如果黑猩猩會回答問題的話
到目前為止,我們所學習的都是程序性的程式設計(procedural programming),也就是程式碼是透過一連串的指令組成的程序或函數,由上而下依序執行不同的程序或是呼叫函數來完成程式的功能。 Python其實是一種物件導向的程式(object oriented programming, 簡稱
Python提供集合做為其資料結構,它就如同高中數學所學集合的概念,集合的內容一般來說是具有某種特性的事物的整體,例如考試分數及格的群體、數字1到100內的所有奇數、球箱內所有球的顏色等。因此,在一個集合中,每個元素的地位都是相同且無序,並且只能出現一次,集合和集合之間,也可以進行交集、聯集、差集等
Python依據變數有效的範圍可以區分為全域變數(Global variable)或區域變數(Local variable)。在函數內宣告的變數為區域變數,有效範圍只有在函數內,函數外部無法引用這個變數;在函數以外宣告的變數為全域變數,它的有效範圍為整個檔案,並且在函數內部也可以引用這個變數。
這篇文章將利用之前所學過的一些東西,包括if敘述、串列、while迴圈、函數等等的觀念,來實作一個撲克牌的小遊戲-21點。
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
十年前,我跟小悟參加了台南政府所舉辦的 24 小時不間斷進食比賽,當年,我以兩分之差,沒擠進金榜。在挑戰時間內,來不及吃狀元糕跟芋頭八寶冰,以致失掉食物王的頭銜。十年後,小悟說,要不要再來回味當年勇?我知道,年輕的我胃袋能撐船,可逝去的青春,最先反映在食慾上。我笑著說不了......
Thumbnail
持著前作的風格,《蜘蛛人:穿越新宇宙》在色彩或畫面的呈現上依舊大膽、前衛,並且嘗試藉由多重宇宙的「優勢」,在成長動畫的既有敘事上,嘗試更多不同的可能性。精彩的安排讓觀看這部作品讓成為十足的享受,並賦予了觀眾再次進場支持的充分動機。
Thumbnail
節目這邊聽 📎錄製時間: 2023.10 汪汪隊立大功! MRT(Mission Readiness Test)是難度最高的國際搜救犬認證! 但是我們有兩位英雄(一人一汪)順利通過這次的認證,拿到了優良的成績! 讓我們歡迎領犬員羅浩芳!就讓她帶著小編、江小姐還有各位聽眾,一起了解這次搜救犬
Thumbnail
這一陣子不少投資標的都在上漲 連成長性沒有科技股強的食品股也在慢慢上升中 今天記錄一下自己食品股大成的最新績效 身為雞肉雙雄的其中一雄 除了飼料、雞肉、雞蛋以外,還跨足了沙拉油、豬肉、海鮮、餐廳等事業體 幾乎可說是一檔食品ETF(還不用付管理費),進去它的官網就可以看到許多不同的事業體
Thumbnail
你現在也許單一個句子可以說得溜,但持續說話覺得尷尬的原因在於:缺乏連接詞。好的連接詞會讓口語表達更精確有力,讓韓國人聽到你說的話不需要猜測意思或重新思考,表達能力也就跟著上升!
Thumbnail
喜歡音樂的羅小咩,不定期將在周六中午12:00與你聊聊戲劇中的音樂,還有音樂中的戲劇。本次介紹:惡作劇之吻、慶餘年、Good Casting、溫柔時光、鋼之鍊金術師這五個戲劇作品的主題曲。
Thumbnail
喜歡音樂的羅小咩,不定期將在周六中午12:00與你聊聊戲劇中的音樂,還有音樂中的戲劇。本次介紹:必娶女人、kill me heal me、錦衣之下、101次求婚、灌籃高手這五個戲劇作品的主題曲。
近期許多地方受到洪水以及颱風的侵襲 但包你發的線路及網路穩定度完全不受到影響 大家可以放心,我們是24小時全年無休不間斷 就算你半夜三點要玩包你發也完全OK 不會像有些系統只在白天開放 而同樣的穩定度也是一大考驗 在這種供電不穩定的情況 也有可能導致其他遊戲斷線 但包你發機房穩定、有備用電源 完全不
Thumbnail
疫情長時間帶來了減少開放性的社交機會,最直接的影響莫過於情緒勒索造成的封閉性失調,感謝國立台灣戲曲學院傑出校友,為身心障礙的大寶寶們帶來一系列精彩的演出,透過精心策劃的舞蹈及雜耍表演,帶給住民體驗了跟以往不同的志工服務內容,見到了久違住民
Thumbnail
每一次TDCA的關愛陪伴,都讓受贈的服務對象感受到滿滿的幸福感,一起協力完成手作皮革鑰匙圈,每一針每一線都在訓練孩子們手眼協調的肢體,透過不同花色皮革來搭配,不僅訓練孩子對色彩的辨識能力,同時也在培養眼界裡的審美觀噢!
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
十年前,我跟小悟參加了台南政府所舉辦的 24 小時不間斷進食比賽,當年,我以兩分之差,沒擠進金榜。在挑戰時間內,來不及吃狀元糕跟芋頭八寶冰,以致失掉食物王的頭銜。十年後,小悟說,要不要再來回味當年勇?我知道,年輕的我胃袋能撐船,可逝去的青春,最先反映在食慾上。我笑著說不了......
Thumbnail
持著前作的風格,《蜘蛛人:穿越新宇宙》在色彩或畫面的呈現上依舊大膽、前衛,並且嘗試藉由多重宇宙的「優勢」,在成長動畫的既有敘事上,嘗試更多不同的可能性。精彩的安排讓觀看這部作品讓成為十足的享受,並賦予了觀眾再次進場支持的充分動機。
Thumbnail
節目這邊聽 📎錄製時間: 2023.10 汪汪隊立大功! MRT(Mission Readiness Test)是難度最高的國際搜救犬認證! 但是我們有兩位英雄(一人一汪)順利通過這次的認證,拿到了優良的成績! 讓我們歡迎領犬員羅浩芳!就讓她帶著小編、江小姐還有各位聽眾,一起了解這次搜救犬
Thumbnail
這一陣子不少投資標的都在上漲 連成長性沒有科技股強的食品股也在慢慢上升中 今天記錄一下自己食品股大成的最新績效 身為雞肉雙雄的其中一雄 除了飼料、雞肉、雞蛋以外,還跨足了沙拉油、豬肉、海鮮、餐廳等事業體 幾乎可說是一檔食品ETF(還不用付管理費),進去它的官網就可以看到許多不同的事業體
Thumbnail
你現在也許單一個句子可以說得溜,但持續說話覺得尷尬的原因在於:缺乏連接詞。好的連接詞會讓口語表達更精確有力,讓韓國人聽到你說的話不需要猜測意思或重新思考,表達能力也就跟著上升!
Thumbnail
喜歡音樂的羅小咩,不定期將在周六中午12:00與你聊聊戲劇中的音樂,還有音樂中的戲劇。本次介紹:惡作劇之吻、慶餘年、Good Casting、溫柔時光、鋼之鍊金術師這五個戲劇作品的主題曲。
Thumbnail
喜歡音樂的羅小咩,不定期將在周六中午12:00與你聊聊戲劇中的音樂,還有音樂中的戲劇。本次介紹:必娶女人、kill me heal me、錦衣之下、101次求婚、灌籃高手這五個戲劇作品的主題曲。
近期許多地方受到洪水以及颱風的侵襲 但包你發的線路及網路穩定度完全不受到影響 大家可以放心,我們是24小時全年無休不間斷 就算你半夜三點要玩包你發也完全OK 不會像有些系統只在白天開放 而同樣的穩定度也是一大考驗 在這種供電不穩定的情況 也有可能導致其他遊戲斷線 但包你發機房穩定、有備用電源 完全不
Thumbnail
疫情長時間帶來了減少開放性的社交機會,最直接的影響莫過於情緒勒索造成的封閉性失調,感謝國立台灣戲曲學院傑出校友,為身心障礙的大寶寶們帶來一系列精彩的演出,透過精心策劃的舞蹈及雜耍表演,帶給住民體驗了跟以往不同的志工服務內容,見到了久違住民
Thumbnail
每一次TDCA的關愛陪伴,都讓受贈的服務對象感受到滿滿的幸福感,一起協力完成手作皮革鑰匙圈,每一針每一線都在訓練孩子們手眼協調的肢體,透過不同花色皮革來搭配,不僅訓練孩子對色彩的辨識能力,同時也在培養眼界裡的審美觀噢!