這篇文章是閱讀Asabeneh的30 Days Of Python: Day 21 - Classes and Objects後的學習筆記與心得。
Python 是物件導向語言,所有的東西在 Python 中都是一個物件 (object),並有自己的屬性 (properties) 與方法 (methods)。
在 JavaScript 中所有東西就只是物件 (object),連 class 也是物件做出來的。constructor 則是產生物件的方法 (method)。
可以用 type()
這個函式來看到物件型別的 class:
num = 10
print(type(num)) # <class 'int'>
與 JavaScript (以下簡稱JS)差不多,命名部分要使用 CamelCase:
class PersonInfo:
pass
print(PersonInfo) # <class '__main__.PersonInfo'>
然後可以透過呼叫剛剛創造的 class 來得到一個物件:
p = PersonInfo()
print(p)
# <__main__.PersonInfo object at 0x000001CB0617EF20>
就像 JS 的 class 可以透過定義 constructor 屬性給 class 增加繼承後物件會拿到的屬性一樣,Python 中透過定義 __init__(self,[, ...])
能做到一樣的事:
class PersonInfo:
def __init__ (self, name, city):
self.name = name
self.city = city
p = PersonInfo("John", "Taipei")
print(p.name) # 'John'
print(p.city) # 'Taipei'
這裡也像 JS,我們可以在 class 中撰寫函式,透過這個 class 產生的物件就能在屬性中發現,並呼叫這些函式:
class PersonInfo:
def __init__(self, name="John", city="Taipei"):
self.name = name
self.city = city
def set_name(self):
self.name = input("Please enter your name: ")
return f"Your new name is: {self.name}"
p = PersonInfo("Wilson", "Taichung")
print(p.set_name())
# Please enter your name: Mary
# Your new name is: Mary
p2 = PersonInfo()
print(f"Hi {p2.name} from {p2.city}!")
# Hi John from Taipei!
__init__
參數一個預設值,在像 p2 這樣沒有給定參數的建構時就不會產生 TypeError;當然這取決於開發者的需求。__init__
中有 self
指到產生的物件本身,額外我們放進去的函式也能這樣使用,像 set_name
就透過這種方式來修改物件內的屬性。JS 中要繼承類別需要使用 extends
keyword,Python 不太一樣,是把要繼承的類別當參數放進子類別中,另外有幾個點要先說明:
__init__
的情況下,會自動沿用母類別的屬性。__init__
,則會覆寫掉母類別的屬性(無法呼叫到)super()
函式,可參考下方例子用法。class PersonInfo:
def __init__(self, name="John", city="Taipei"):
self.name = name
self.city = city
def set_name(self):
self.name = input("Please enter your name: ")
return f"Your new name is: {self.name}"
def get_info(self):
return {"name": self.name, "city": self.city}
class Student(PersonInfo):
def __init__(self, name="unregistered", city="unknown", course="unsigned"):
super().__init__(name, city)
self.course = course
def get_info(self):
return {"course": self.course}
p = Student("Wilson", "Taichung", "30 days of Python")
print(p.get_info())
# {'course': '30 days of Python'}
p2 = Student()
print(f"Hi {p2.name} from {p2.city}!")
# Hi unregistered from unknown!
Student(PersonInfo)
就是 Studnet
這個類別繼承了 PersonInfo
這個類別。Student
內有自己的 __init__
,這裡面又 super
,並把接收到的name
和city
參數放進引數中給 PersonInfo
。p
物件呼叫 get_info()
方法,從回傳結果可以看出是拿到 Student
的 get_info()
而不是 PersonInfo
的—對應到上方第4點。p2
物件呼叫 name
和 city
在 Student
類別中並沒有定義這些屬性,因此會拿到母類別,也就是 PersonInfo
的屬性。