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

更新於 發佈於 閱讀時間約 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
大家好,我是woody,是一名料理創作者,非常努力地在嘗試將複雜的料理簡單化,讓大家也可以體驗到料理的樂趣而我也非常享受料理的過程,今天想跟大家聊聊,除了料理本身,料理創作背後的成本。
Thumbnail
哈囉~很久沒跟各位自我介紹一下了~ 大家好~我是爺恩 我是一名圖文插畫家,有追蹤我一段時間的應該有發現爺恩這個品牌經營了好像.....快五年了(汗)時間過得真快!隨著時間過去,創作這件事好像變得更忙碌了,也很開心跟很多厲害的創作者以及廠商互相合作幫忙,還有最重要的是大家的支持與陪伴🥹。  
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
「傳」是傳授,「承」是繼承;由諸佛菩薩將殊勝的法教傳承給祖師,再經過祖祖輩輩的弘傳,方能使法燈常明,法輪常轉。擁有清淨不間斷法流傳承的上師,其加持力就更加地殊勝具力!依怙主 究給.企千法王為薩迦察派主要而神聖的成就者上師,亦為觀音山法脈殊勝的傳承祖師。尊貴 龍德上師致力於落實藏傳佛教根留臺灣的理念,
Thumbnail
繼上一篇的破除執念,我按照內文的方式做,最近狀態的確好很多了。我偶爾會找對方說說話,有趣的是,偶爾還是會被激起一些情緒,但那比較像是內在小孩的BUG被抓到了,和對對方的情感關係不大。 比如說對方沒回覆,或是回答簡短的時候,我會情緒激動,因為我感受到"自己不被在乎"和"自己不值得"的負面信念。我同時
Thumbnail
讓愛心文具成為教育的養分 在尼泊爾,佛學院承載著重要的教育責任。很多家庭自小就將最優秀的孩子送來佛學院,讓他們能接受系統的教育和培養。有些孩子則來自非常貧困的家庭,佛學院也提供他們完善受教育的機會。在這趟尼泊爾助學行,德內ㄦ特別訂製準備了3,200個文具組及16箱色鉛筆,將我們的關懷送到了12所學
Thumbnail
世堅無奇不有,如果以一種單一的方式存活,豈不是錯過很多種可能性?
Thumbnail
這個章節主要介紹了Swift程式語言中物件導向程式設計的基本概念,包括類別、建構子、公開、私有、受保護等等的概念。同時,也介紹了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射等進階特性。
Thumbnail
這一節談的是用物件導向程式設計(object-oriented programming, OOP)的方式來實作隨機漫步。
Thumbnail
※ OPP第一大核心-封裝 封裝的精神在於將「方法」、「屬性」和「邏輯」包裝在類別裡面,透過類別的實例來實現。這樣外部物件不需要了解內部的實現細節,只需要知道如何使用該類別提供的接口即可。換句話說,封裝是將內部細節隱藏起來,只暴露必要的部分給使用者。 封裝的核心概念是,使用者如果想要接觸資料,只
Thumbnail
十年前,我跟小悟參加了台南政府所舉辦的 24 小時不間斷進食比賽,當年,我以兩分之差,沒擠進金榜。在挑戰時間內,來不及吃狀元糕跟芋頭八寶冰,以致失掉食物王的頭銜。十年後,小悟說,要不要再來回味當年勇?我知道,年輕的我胃袋能撐船,可逝去的青春,最先反映在食慾上。我笑著說不了......
Thumbnail
本文介紹了Python中的物件導向程式設計的重要概念,包括類別、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射。每個概念都有對應的程式碼範例來說明其用法和功能。這些概念對於理解和使用Python進行物件導向程式設計至關重要。
Thumbnail
前幾篇討論到各種裝飾器的用法,本文將介紹另外一種裝飾器,可以將方法轉換成屬性來使用。 property也可以動態的取出物件的值,隨著時間或其他運算改變所產生的值,讓我們繼續往下看更多介紹吧。
Thumbnail
大家好,我是woody,是一名料理創作者,非常努力地在嘗試將複雜的料理簡單化,讓大家也可以體驗到料理的樂趣而我也非常享受料理的過程,今天想跟大家聊聊,除了料理本身,料理創作背後的成本。
Thumbnail
哈囉~很久沒跟各位自我介紹一下了~ 大家好~我是爺恩 我是一名圖文插畫家,有追蹤我一段時間的應該有發現爺恩這個品牌經營了好像.....快五年了(汗)時間過得真快!隨著時間過去,創作這件事好像變得更忙碌了,也很開心跟很多厲害的創作者以及廠商互相合作幫忙,還有最重要的是大家的支持與陪伴🥹。  
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
「傳」是傳授,「承」是繼承;由諸佛菩薩將殊勝的法教傳承給祖師,再經過祖祖輩輩的弘傳,方能使法燈常明,法輪常轉。擁有清淨不間斷法流傳承的上師,其加持力就更加地殊勝具力!依怙主 究給.企千法王為薩迦察派主要而神聖的成就者上師,亦為觀音山法脈殊勝的傳承祖師。尊貴 龍德上師致力於落實藏傳佛教根留臺灣的理念,
Thumbnail
繼上一篇的破除執念,我按照內文的方式做,最近狀態的確好很多了。我偶爾會找對方說說話,有趣的是,偶爾還是會被激起一些情緒,但那比較像是內在小孩的BUG被抓到了,和對對方的情感關係不大。 比如說對方沒回覆,或是回答簡短的時候,我會情緒激動,因為我感受到"自己不被在乎"和"自己不值得"的負面信念。我同時
Thumbnail
讓愛心文具成為教育的養分 在尼泊爾,佛學院承載著重要的教育責任。很多家庭自小就將最優秀的孩子送來佛學院,讓他們能接受系統的教育和培養。有些孩子則來自非常貧困的家庭,佛學院也提供他們完善受教育的機會。在這趟尼泊爾助學行,德內ㄦ特別訂製準備了3,200個文具組及16箱色鉛筆,將我們的關懷送到了12所學
Thumbnail
世堅無奇不有,如果以一種單一的方式存活,豈不是錯過很多種可能性?
Thumbnail
這個章節主要介紹了Swift程式語言中物件導向程式設計的基本概念,包括類別、建構子、公開、私有、受保護等等的概念。同時,也介紹了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射等進階特性。
Thumbnail
這一節談的是用物件導向程式設計(object-oriented programming, OOP)的方式來實作隨機漫步。
Thumbnail
※ OPP第一大核心-封裝 封裝的精神在於將「方法」、「屬性」和「邏輯」包裝在類別裡面,透過類別的實例來實現。這樣外部物件不需要了解內部的實現細節,只需要知道如何使用該類別提供的接口即可。換句話說,封裝是將內部細節隱藏起來,只暴露必要的部分給使用者。 封裝的核心概念是,使用者如果想要接觸資料,只
Thumbnail
十年前,我跟小悟參加了台南政府所舉辦的 24 小時不間斷進食比賽,當年,我以兩分之差,沒擠進金榜。在挑戰時間內,來不及吃狀元糕跟芋頭八寶冰,以致失掉食物王的頭銜。十年後,小悟說,要不要再來回味當年勇?我知道,年輕的我胃袋能撐船,可逝去的青春,最先反映在食慾上。我笑著說不了......
Thumbnail
本文介紹了Python中的物件導向程式設計的重要概念,包括類別、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射。每個概念都有對應的程式碼範例來說明其用法和功能。這些概念對於理解和使用Python進行物件導向程式設計至關重要。
Thumbnail
前幾篇討論到各種裝飾器的用法,本文將介紹另外一種裝飾器,可以將方法轉換成屬性來使用。 property也可以動態的取出物件的值,隨著時間或其他運算改變所產生的值,讓我們繼續往下看更多介紹吧。