MUR018 沈思Python建構式

目錄

沈思Python建構式

紫式晦澀每日一篇文章第18天

前言

  1. 今天是2022年第16天, 全年第3週, 一月的第三個週六. 今天來深思「構造Class」的細節思想, 讓思考昇華到更根本的原因上.

  2. 今天的素材主要來自各篇關於Python 建構式(constructor)的文章

Python構造式

  1. 構造式(Constructor)簡介:
  • 在創建類的對象時, 使用 Python 編程語言中的構造函數(Constructor),同時驗證對像是否有足夠數量的資源來執行任何類型的啟動任務。
  • 一種特殊類型的函數或方法,其目的是初始化類的成員,通常分為兩種類型。
  • 這些函數基本上是「參數化構造函數」和「非參數化構造函數」
  • 。前者致力於考慮參數的想法,後者認為它不需要任何參數。

技法: 預設構造式&參數化構造式

  1. 預設構造式(Default Constructor):
  • 不接受任何參數。

  • 在稱為 self 的默認構造函數的情況下存在默認參數。此參數指的是為此類創建的對象。

  • 基本代碼

 1class  sample:
 2
 3    # default constructor
 4    def __init__(self):
 5        # initializing variable instance
 6        self.number_variable=1001
 7
 8    # a method
 9    def print_method(self):
10        print(number variable : ,self.number_variable)
  • 執行
1obj=sample()
2obj.print_method()
  1. 參數化構造式(Parameterized Constructor):
  • 參數化構造函數接受其中的參數。
  • 就像這裡的默認構造函數一樣,創建的第一個參數引用這個類的實例。
  • 程序員需要並定義其餘參數以引用實例變量。
  • 基本代碼
 1class  sample:
 2    # parameterized constructor
 3    def __init__(self ,  id , name , age , gender, doj , dob ):
 4        self.id_value = id
 5        self.name_value = name
 6        self.age_value =  age
 7        self.gender_value = gender
 8        self.doj_value = doj
 9        self.dob_value = dob
10    # method to output attributes 
11    def print_output(self):
12        print(Id value :, self.id_value)
13        print(name_value :, self.name_value)
14        print(age_value :, self.age_value)
15        print(gender_value :, self.gender_value)
16        print(doj_value :, self.doj_value)
17        print(dob_value :, self.dob_value)
  • 執行
1obj1=sample(101,Terry,27,male,10072015,10071993)
2obj1.print_output()

心法: 構造式的工作原理-__init__()函數與自引用

  1. __init__()函數:
  • 該函數在相應類的對象實例創建時調用。
  • 這個構造函數是使用 def 關鍵字來確認的,這與所有其他函數聲明非常相似。
  • 在函數中的這些初始化函數聲明中另一個值得注意的事情將是前面和後綴的雙下劃線。
1def __init__(self,salary_arg)
  1. 自引用(Self Reference):
  • self 引用了物件本身(Object itself)。
  • self 可以指代與其所涉及的類相關的函數和變量。
  • 必須是構造函數聲明中最重要的參數。
  • 它表示期望指數與該對象的屬性一起使用。
1def __init__(self,Employee_name,Employee_id, Employee_age):
2    self.Employee_name = name;
3    self.Employee_id = id;
4    self.Employee_age = age

用法: 初始化, 實例變數

  1. 構造式的優點:
  • 主優點: 在「初始化(Initialize)」有莫大幫助
  • 實例變數(Instance variables): 使用建構式可以初始化的最後狀態
  • 可以使用構造函數省略默認值初始化.
  • 當 python 類創建物件時。, 造函數將是第一個開始執行的代碼段,這使得所有初始化都作為程序的第一個工作實例發生。
  • 可以使用和不使用參數來啟動構造函數.

概覽__init__()方法

  1. __init__()方法創造物件: __init__()方法是物件導向編程的核心, 因為其能「創造物件(create objects)」

  2. 物件導向:

  • 面向物件寫程式(OOP)是一種編程範式,包括定義物件並與它們互動。
  • 物件是複雜變數和函式的集合,可用於表示按鈕、飛機或人等真實實體。
  • 要在Python中宣告、初始化和操作物件,我們使用類。 它們作為建立物件的模板。
  • 下圖說明了這個想法:
  1. 類別是物件的克隆藍圖:
  • 類(Class)定義並構建從中建立的所有物件。
  • 類為物件(Object)工廠。
  • 類使用方法(Method)和建構式(Constructor)來建立和定義物件。
  1. 特殊方法(Special methods):
  • 特殊方法透過其名稱兩側的雙下劃線標識,例如__init__。
  • Python使用特殊方法來增強類的功能。
  • 他們中的大多數人在後臺工作,並在程式需要時自動呼叫。
  • 您不能顯式呼叫他們。
  • 例如,當您建立新物件時,Python會自動呼叫__new__方法,而該方法又會呼叫__init__方法。
  • 當您列印()物件時,會呼叫__str__方法。 另一方面,使用者定義的方法,如stefi.run(),被顯式呼叫。
  1. 構造式(Constructor):
  • 建構函式是程式呼叫物件建立的特殊方法。
  • 建構函式在類中用於將資料成員初始化到物件。
  • 特殊方法__init__是Python建構函式。

類別物件兩大功能: 屬性引用, 實例化

官方文檔的「類別物件(Class Object)」

  1. 類別物件核心功能: 類別物件的兩種核心操作, 為「屬性引用(Attribute References)」與「實例化(Instantiation)」 .

  2. 屬性引用(Attribute References):

  • 使用Python中所有屬性引用的標準語法:obj.name
  • 有效屬性名稱(Valid attribute names): 建立類物件時「類名稱空間(Class’s namespace)」中的所有名稱。
  • 定義實例:
1class MyClass:
2    """A simple example class"""
3    i = 12345
4
5    def f(self):
6        return 'hello world'
  • 這裡的MyClass.i(類屬性)與MyClass.f(類方法)是有效的屬性引用.
  • MyClass.i(類屬性) 返回「正整數物件(Integer Object)」
  • MyClass.f(類方法) 返回「函數物件(Function Object)」
  • 可以透過指定, 來感變MyClass.i的數值
  • __doc__也是有效特徵, 返回文檔"""A simple example class"""
  1. 實例化(Instantiation):
  • 把「類別物件」視為「無參數函數」來產生「新的類別實例(new instance of the class)」.
  • 實例:
1x = MyClass()
  • 實例化(Instantiation): 實例化操作創建空物件.
  • 類別創造「具有特定初始值的實例物件」, 所以需要定義特殊方法__init__()
  • 實例:
1def __init__(self):
2    self.data = []
  • 如果一個類別有定義__init__()方法, 實例化就會自動啟動. 也就是x = MyClass()在操作的事情.

建構式實例化實務

  1. 例子: 「學生」類別, 「學生成績」類別:
  • 所謂的「類別」, 可以很融通. 例如「學生」類別包含一個學生的「個人資訊」; 「學生成績」類別包含了一個學生的「課業表現」.
  • 實例
 1# 定義「學生」類別, 屬性為「個人資訊」
 2class student:
 3  def __init__(self,name,age):
 4    self.name=name
 5    self.age=age
 6 
 7# 定義「學生成績」類別, 屬性為「課業表現」, 方法有「計算平均成績」
 8class student_marks:
 9  def __init__(self,name,english,maths,science,sst):
10    self.name=name
11    self.english=english
12    self.maths=maths
13    self.science=science
14    self.sst=sst
15 
16  def calculate_avg_marks(self):
17    total_marks=self.english+self.maths+self.science+self.sst
18    avg_marks=total_marks/4
19    return avg_marks
20 
21# 實例化四個「學生成績」物件
22student1=student_marks("Ashwini",20,12,14,15)
23student2=student_marks("Ashu",10,18,16,9)
24student3=student_marks("Sonu",16,14,20,11)
25student4=student_marks("Sushant",20,20,20,20)
26
27# 計算四個「學生成績物件」的平均分數
28print(student1.calculate_avg_marks())
29print(student2.calculate_avg_marks())
30print(student3.calculate_avg_marks())
31print(student4.calculate_avg_marks())
  1. 這個點很有趣, 適當的構造「類別」可以有效管理複雜度. 任何東西不要超過3個點, 超過我們就分解, 也是管理複雜系統的重要心法.

  2. 例子:「學生」, 「員工」都是「人」:

  • 活用「繼承」的概念, 可以實踐「學生」, 「員工」都是「人」這句大白話
  • 實例
 1### 定義「人」類別
 2class Person():
 3  def __init__(self,name):
 4    print("Person Init called.")
 5    self.name = name
 6 
 7### 定義「學生」類別, 基於「人」類別
 8class Student(Person):
 9  def __init__(self, name):
10    Person.__init__(self, name)
11    print("Student Init called.")
12    self.name = name
13  def display(self):
14    print("Student",self.name)
15
16### 定義「員工」類別, 基於「人」類別 
17class Employee(Person):
18  def __init__(self, name):
19    Person.__init__(self, name)
20    print("Employee Init called.")
21    self.name = name
22  def display(self):
23    print("Employee",self.name)
24 
25### 實例化Vicky學生
26student = Student('Vicky')
27student.display()
28
29### 實例化Vikas員工
30employee= Employee('Vikas')
31employee.display()
  • 更好的實例:
 1### 定義「人」類別
 2class Person():
 3    def __init__(self,name):
 4        print("Person Init called.")
 5        self.name = name
 6
 7### 定義「學生」類別, 繼承「人」類別
 8### 利用「父類別」的「構造式 `__init__()`
 9class Student(Person):
10    def __init__(self, name):
11        print("Student Init called.")
12        self.name = name
13        Person.__init__(self, name)
14 
15    def display(self):
16        print("Student",self.name)
17
18student = Student('Vicky')
19student.display()
  1. 或用這種繼承思想, code可以更簡潔, 管理複雜度.

  2. 感覺寫論文是不是也能這樣呢? 要把哪些sentence pattern 給抽象畫出來呢? 如何建立資料庫呢? Python for Latex之類的呢?

  3. Super()方法:

  • 在「子類別(Subclass)」裡面使用方法super()可以得到「超類別(Superclass)」裡面的「暫時物件(temporary)」.
  • 這個暫時物件的方法, 可以被使用.
  • 實例:
 1### 定義「長方體」類別
 2class Cuboid:
 3    ### 構造「長寬高」屬性
 4    def __init__(self, length, width,height):
 5        self.length = length
 6        self.width = width
 7        self.height=height
 8    ### 方法計算表面積
 9    def total_surface_area(self):
10        return 2*(self.length * self.width +self.width*self.height+self.length*self.height)
11
12### 「立方體」類別, 寫法一: 不使用繼承 
13class Cube:
14    def __init__(self, length):
15        self.length = length
16 
17    def total_surface_area(self):
18        return 6*self.length * self.length
19
20### 「立方體」類別, 寫法二: 使用繼承
21class Cube(Cuboid):
22    def __init__(self, length):
23        super().__init__(length,length,length)
24 
25cuboid=Cuboid(5,4,3)
26print(cuboid.total_surface_area())
27cube=Cube(5)
28print(cube.total_surface_area())

後記

  1. 到此回顧了一些__init__()的技術細節, 以及實例思考「繼承」的一些用法.

  2. 感覺寫著寫著偏離了「構造式」的原主題, 但因為這邊的水很深, 所以100分鐘大概就cover這些內容. 我們寫作也要懂得取捨, 一步一腳印慢慢往前. 天天向上, 共勉之!

2022.01.16. 紫蕊 於 西拉法葉, 印第安納, 美國.

版權

CC BY-NC-ND 4.0

評論