<jupyter_start><jupyter_text>鍛鍊你的資料分析力 | Python 程式設計> 類別郭耀仁  from [DATAINPOINT](https://www.datainpoint.com/) > The main "actors" in the object-oriented paradigm are called objects.  程式封裝的層級- 套件（Libraries）    - 模組（Modules）        - **類別（Classes）**            - 函式（Functions）  程式封裝的層級- 將數行程式碼組合為一個函式（Function）- **將數個函式組合為一個類別（Class）**- 將數個類別組合為一個模組（Module）- 將數個模組組合為一個套件（Library）  大綱- 目標與準則- 定義類別- 繼承- 隨堂練習  目標與準則  目標：從程式設計到軟體開發- 強韌 Robustness: 軟體考慮到所有可能的輸入情況，並對應到正確的輸出情況- 調適 Adaptability: 軟體可以與時俱進- 重複使用 Reusability: 功能模組化，可以在未來的開發直接使用  物件導向（Object-oriented programming）是讓程式碼達成目標的途徑  準則：物件導向的程式設計考量- 封裝 Encapsulation: 將變數與函式與物件進行綁定- 摘要 Abstraction: 描述出物件重要的資訊與行為- 模組化 Modularity: 拆解物件為不同作用的小單位  定義類別  類別是實踐物件導向的第一個主題- 自訂類別（Class）模擬真實世界的情況- 每個物件都是一個特定類別- 類別提供成員屬性（member attributes）提供靜態資訊、提供成員函式（member functions）提供動態行為  自訂類別中的元件別稱- 成員屬性（member attributes）：有時也稱呼為欄位（fields）、物件變數（instance variables）或資料（data members）- 成員函式：有時也稱呼為方法（methods）  自訂類別程式碼結構- 使用 `class` 保留字- 類別名稱為**單數**名詞- 以長字串 """Docstrings""" 撰寫類別說明 ```pythonclass ClassName:    """    Docstrings    """    def method_of_class(self):         ...        return```  綁定函式到類別之中`self` 用來表達未來將被創建出來的那個物件。<jupyter_code>class Calculator:
    def add(self, a, b):
        return a + b
calculator = Calculator() # 創建物件
calculator.add(5, 6)      # 呼叫方法<jupyter_output><empty_output><jupyter_text>綁定屬性到類別之中初始化方法 `__init__(self)` 在宣告以自訂類別創建物件的當下被觸發。 ```pythonclass ClassName:    """    Docstrings    """    def __init__(self, attr):        self._attr = attr```<jupyter_code>class Calculator:
    def __init__(self, a, b):
        self._a = a
        self._b = b
calculator = Calculator(5, 6) # 創建物件
print(calculator._a)          # 檢視屬性
print(calculator._b)          # 檢視屬性<jupyter_output>5
6<jupyter_text>綁定方法與屬性的類別透過 `self.attr` 運用綁定在類別上的屬性。<jupyter_code>class Calculator:
    def __init__(self, a, b):
        self._a = a
        self._b = b
    def add(self):
        return self._a + self._b
calculator = Calculator(5, 6)
calculator.add()<jupyter_output><empty_output><jupyter_text>在類別中呼叫方法<jupyter_code>class Calculator:
    def __init__(self, a, b):
        self._a = a
        self._b = b
    def add(self):
        return self._a + self._b
    def add_then_squared(self): # (a+b)**2
        add_res = self.add()
        return add_res**2
calculator = Calculator(5, 6)
calculator.add_then_squared()<jupyter_output><empty_output><jupyter_text>在類別藉由呼叫方法新增屬性並非只有 `__init__` 方法可以新增屬性。<jupyter_code>class Calculator:
    def __init__(self, a, b):
        self._a = a
        self._b = b
    def add(self):
        self._a_plus_b = self._a + self._b
    def add_then_squared(self): # (a+b)**2
        self.add()
        return (self._a_plus_b)**2
calculator = Calculator(5, 6)
calculator.add_then_squared()<jupyter_output><empty_output><jupyter_text>物件、類別、屬性與方法- 我們使用類別創建物件（Objects）    - 我們使用類別（Classes）綁定屬性與方法        - 屬性（Attributes）描述靜態資訊        - 方法（Methods）描述動態行為  繼承  繼承：定義新的類別時可以沿用既有類別的所有方法與屬性```pythonclass NewClassName(ClassName)```<jupyter_code>class NewCalculator(Calculator):
    pass
new_calculator = NewCalculator(5, 6)
new_calculator.add()<jupyter_output><empty_output><jupyter_text>繼承後可以新增方法且保存既有方法```pythonclass NewClassName(ClassName):    def new_method(self):        ...```<jupyter_code>class NewCalculator(Calculator):
    def subtract(self):
        return self._a - self._b
new_calculator = NewCalculator(5, 6)
print(new_calculator.add())
print(new_calculator.subtract())<jupyter_output>None
-1<jupyter_text>繼承後可以改寫方法<jupyter_code>class NewCalculator(Calculator):
    def add(self):
        return self._a * self._b
new_calculator = NewCalculator(5, 6)
new_calculator.add()<jupyter_output><empty_output><jupyter_text>繼承後可以新增屬性<jupyter_code>class NewCalculator(Calculator):
    def __init__(self, a, b, c):
        super().__init__(a, b)
        self._c = c
new_calculator = NewCalculator(5, 6, 5566) # 創建物件
print(new_calculator._a)                   # 檢視屬性
print(new_calculator._b)                   # 檢視屬性
print(new_calculator._c)                   # 檢視屬性<jupyter_output>5
6
5566<jupyter_text>繼承是實踐「集合」的自然方式以國家、程式與行政區為例：- 國家（Country）    - 城市（City）        - 行政區（Town）  母集合與子集合- 城市是行政區的母集合（Superset）、行政區是城市的子集合（Subset）- 國家是城市的母集合（Superset）、城市為國家的子集合（Subset）<jupyter_code>class Country:
    def __init__(self, country_name):
        self._country_name = country_name
    def get_country_name(self):
        return self._country_name
twn = Country('Taiwan')
twn.get_country_name()
class City(Country):
    def __init__(self, country_name, city_name):
        super().__init__(country_name)
        self._city_name = city_name
    def get_city_name(self):
        return "{}, {}".format(self._city_name, self._country_name)
tpe = City('Taiwan', 'Taipei')
tpe.get_city_name()
class Town(City):
    def __init__(self, country_name, city_name, town_name):
        super().__init__(country_name, city_name)
        self._town_name = town_name
    def get_town_name(self):
        return "{}, {}, {}".format(self._town_name, self._city_name, self._country_name)
daan = Town('Taiwan', 'Taipei', 'Da-an')
daan.get_town_name()<jupyter_output><empty_output><jupyter_text>隨堂練習  隨堂練習：創建類別 `Calculator` 具有 4 個方法 `add()`、`subtract()`、`multiply()` 與 `divide()`- 預期輸入：兩個數值- 預期輸出：一個數值<jupyter_code>class Calculator:
    """
    >>> calculator = Calculator()
    >>> calculator.add(5, 6)
    11
    >>> calculator.subtract(5, 6)
    -1
    >>> calculator.multiply(5, 6)
    30
    >>> calculator.divide(6, 3)
    2.0
    """<jupyter_output><empty_output><jupyter_text>隨堂練習：創建類別 `Aggregator` 具有 2 個方法 `product()` 與 `summation()`- 預期輸入：彈性參數 `*args`- 預期輸出：一個數值<jupyter_code>class Aggregator:
    """
    >>> aggregator = Aggregator()
    >>> aggregator.product(5, 5, 6, 6)
    900
    >>> aggregator.summation(5, 5, 6, 6)
    22
    """<jupyter_output><empty_output><jupyter_text>隨堂練習：創建類別 `NewCalculator` 繼承先前定義的 `Calculator` 類別，加入 3 個方法 `power()`、`get_modulo()` 與 `get_quotient()`- 預期輸入：兩個數值- 預期輸出：一個數值<jupyter_code>class NewCalculator(Calculator):
    """
    >>> new_calculator = NewCalculator()
    >>> new_calculator.add(5, 6)
    11
    >>> new_calculator.subtract(5, 6)
    -1
    >>> new_calculator.multiply(5, 6)
    30
    >>> new_calculator.divide(6, 3)
    2.0
    >>> new_calculator.power(5, 2)
    25
    >>> new_calculator.get_modulo(5, 6)
    5
    >>> new_calculator.get_quotient(5, 6)
    0
    """<jupyter_output><empty_output><jupyter_text>隨堂練習：創建類別 `NewAggregator` 繼承先前定義的 `Aggregator` 類別，加入 2 個方法 `length()` 與 `mean()`- 預期輸入：彈性參數 `*args`- 預期輸出：一個數值<jupyter_code>class NewAggregator(Aggregator):
    """
    >>> new_aggregator = NewAggregator()
    >>> new_aggregator.product(5, 5, 6, 6)
    900
    >>> new_aggregator.summation(5, 5, 6, 6)
    22
    >>> new_aggregator.length(5, 5, 6, 6)
    4
    >>> new_aggregator.mean(5, 5, 6, 6)
    5.5
    """<jupyter_output><empty_output><jupyter_text>隨堂練習：創建類別 `Recursives` 具有 2 個方法- `factorial(n)`- `fibonacci(n)` ```pythondef factorial(n):    if n == 0:        return 1    elif n == 1:        return 1    else:        return n*factorial(n-1)  recursive happens heredef fibonacci(n):    if n == 0:        return 0    elif n == 1:        return 1    else:        return fibonacci(n-1) + fibonacci(n-2)  recursive happens here```<jupyter_code>class Recursives:
    """
    >>> recur = Recursives()
    >>> recur.factorial(0)
    1
    >>> recur.fibonacci(0)
    0
    >>> recur.factorial(1)
    1
    >>> recur.fibonacci(1)
    1
    >>> recur.factorial(2)
    2
    >>> recur.fibonacci(2)
    1
    """
# %load ../test_cases/test_cases_08.py<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1411051035210339, 'fraction_numerical': 0.018726097850454964, 'mean_word_length': 3.842911877394636, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 144, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '621618', 'license': 'MIT', 'n_tokens_mistral': 3812, 'n_tokens_neox': 3846, 'n_words': 498, 'path': 'notebooks/08-classes.ipynb', 'repo_name': 'datainpoint/classroom-introduction-to-python', 'size': '7583'}