今天來做一個 class Student
吧!
接續上一篇的問題:
他所生產出的物件需要有什麼特性、行為?
姓名、體重、成績、興趣應該算是他們的特性吧!
行為呢?讀書、吃飯、運動是學生們正常的行為。
要怎麼表達,學生的特性與行為呢?
constructor
)中。先來處理特性的部分!
class Student:
def __init__(self):
self.name = "Bob"
self.weight = 50
self.gpa = 3.6
self.hobby = ['play baseball', 'watch movie']
測試看看,Student產生出的物件是不是都有姓名、體重、成績、興趣這些特性
Bob = Student()
print(f"Bob's name = {Bob.name}")
print(f"Bob's weight = {Bob.weight}")
print(f"Bob's gpa = {Bob.gpa}")
print("Bob's hobby = ", end = "")
for hobby in Bob.hobby:
print(hobby, end = " ")
一切正常,那我們再做一個物件
John = Student()
print(f"John's name = {John.name}")
print(f"John's weight = {John.weight}")
print(f"John's gpa = {John.gpa}")
print(f"John's hobby = {', '.join(John.hobby)}")
欸?John 是不是拿到 Bob 的學生證?還是John是複製人?
不是啦~原因是我們沒有做到客製化!
建構子後方在多給幾個參數!
class Student:
def __init__(self, name, weight, gpa, hobby):
self.name = name
self.weight = weight
self.gpa = gpa
self.hobby = hobby
再來測試看看吧!
John = Student("John", 65, 2.5, ['sing', 'dance'])
print(f"John's name = {John.name}")
print(f"John's weight = {John.weight}")
print(f"John's gpa = {John.gpa}")
print(f"John's hobby = {', '.join(John.hobby)}")
搞定啦!
不過,我們稍微再升級一下!
與其傳入一個列表,不如傳入 *hobbies
,因為我們並不知道這個學生到底有多少興趣。
相較傳入列表來說,這種方式比較常見。
class Student:
def __init__(self, name, weight, gpa, *hobbies):
self.name = name
self.weight = weight
self.gpa = gpa
self.hobby = []
for hobby in hobbies:
self.hobby.append(hobby)
宣告 Student 的物件,從第四個參數開始都是學生興趣。
John = Student('John', 67, 3.8, 'sleep', 'eat')
不知道你沒有發現「建構子定義式中的參數」永遠比「使用建構子需傳入的參數」多一個?
def __init__(self, name, weight, gpa, hobby): # 5 parameters
John = Student("John", 65, 2.5, ['sing', 'dance']) # 4 arguments
def __init__(self): # 1 parameter
John = Student() # 0 argument
這一個差距就是 self
關鍵字!
簡單來說,self
就是代表物件本身。
如果學過
C++
,JavaScript
,你可能會見過代表物件自己的this
關鍵字
在Python
中,我們使用self
self
this
的功能其實是相同的,只是不同語言有不同的語法
證明一下,self
就是代表物件本身!
class myClass:
def __init__(self):
print(id(self))
obj = myClass()
print(id(obj))
這兩個輸出分別印出
id(self)
和id(obj)
結果兩個輸出是完全相等的,代表兩者是相同的東西
在物件的背後其實有一個變數儲存了該物件的所有屬性,而這個變數的型態是一個字典。
語法是 vars()
,括號裡的參數可以是關鍵字 self
或物件名稱,用法參見以下範例!
class myClass:
def __init__(self):
self.name = 'Bob'
print(vars(self))
print('name' in vars(self))
class myClass:
def __init__(self):
self.name = 'Bob'
bob = myClass()
print(vars(bob))
print('name' in vars(bob))
特別注意的是屬性名稱會以字串來儲存,因此從上述的例子可以看到我們以 'name' in vars(self)
來判斷物件是否有屬性 name
,而非 name in vars(self)
。
今天就先設定 class Student
的特性,下一次我們來讓學生有些行為!