Python是一種物件導向的程式語言。在Python中,幾乎所有的東西都是一個物件(object)。
類別(class)就像構建物件的「藍圖」,或者說是一個構建物件的函式。
另外,物件中的方法是指在物件裡的函式,物件中的屬性是指物件裡的變數。
要創建一個類,使用關鍵字 class
。
例如創建一個名為 MyClass
的類別,他有一個名為 x
的實例屬性。
class MyClass:
def __init__(self):
self.x = 5
我們可以使用名為 MyClass
的類別來構建物件。在物件中的變數叫作屬性。
例如構建一個名為 p1
的物件,該物件含有屬性x
。
class MyClass:
def __init__(self):
self.x = 5
p1 = MyClass()
print (p1.x)
可以稍微將有回傳東西的函式與類別做連結,但物件在函式之上,因為我們可以從它裡面取用東西
def myFunc():
x = 1
y = 7
return x
class Myclass:
def __init__(self):
self.x = 1
self.y = 7
f = myFunc()
print (f)
c = MyClass()
print (c.x, c.y)
class MyClass:
def __init__(self):
self.x = int() #或任意數字
self.l = list() #[] 也對
self.d = dict() #{} 也對
c = MyClass()
print(c.x, c.l, c.d)
試寫一個類別,該類別含有一個int
變數x
、一個空的list
和一個空的dict
。
我們可以像下面這樣修改用上面構建出來的物件裡的屬性(變數)。
p1 = MyClass()
p1.x = 327
c.l.append(1)
c.d['Mandy']=327
承上題,將你定義的那個空的list
使用append
放入一個int
變數1
,再將你定義的那個空的dict
放入鍵值對'Mandy':327
。
通常類別取名字的時候首字母會大寫,比容易讓人認得出這是個類別。由於物件是變數,所以可以不用管,但有一派是不管物件或類別都取首字母大寫的名字。另外函式都建議首字母小寫,不會變的變數(constant)用全大寫。
def myFunc(): pass # 當一個類別或函式什麼屬性都沒有請這樣寫
class MyClass: pass
myClassX = MyClass()
MyClassX = MyClass()
PI = 3.14159
物件除了變數外也可以有函式。不過在物件裡函式叫作方法。
所有的類別都有一個叫做 __init__()
的函式,它總是在類別被構建成物件時執行。
使用 __init__()
函式為物件中的變數賦值,或者在構建物件時進行其他操作。
例如構建一個名為 Person
的類別,使用 __init__()
函式為 name
和 age
賦值。
self
是對類別的代稱,用於類別中函式的呼叫或變數的引用。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person("Mandy", 20)
print (p1.name)
print (p1.age)
__init__()
方法。前面的程式碼相當於
class Person: pass
p1 = Person()
p1.name = "Mandy"
p1.age = 20
print (p1.name)
print (p1.age)
class MyHello:
def __init__(self):
print("Hello")
試寫一個名叫MyHello
的類別,使該類別在構件時印出 Hello。
class MyHello:
#TO-DO
c = MyHello() #印出 Hello
class MyString:
def __init__(self,s):
print(s)
試寫一個名叫MyString
的類別,使該類別在構件時印出字串s
。
class MyString:
#TO-DO
s = "Hello"
c = MyString(s) #印出 s
在一個類別中,我們有些屬性是可以共用的,例如
class Car: weels=4 # (Class Attribute) def __init__(self,name): self.name = name #(Instance Attribute)
print(Car.weels) my_car = Car('SaberSR') his_car = Car('CottonSR') print(my_car.weels) Car.weels=8 print(his_car.weels) my_car.weels = 4 print(his_car.weels)
可以看到,只要我們修改類別的屬性,所有的屬性都會受到影響
物件除了變數外也可以有函式。不過在物件裡函式叫作方法。
讓我們在上面的Person
類別中寫一個方法。
插入一個輸出問候語的函式,並在p1
物件上執行。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def myfunc(self):
print("Hello my name is " + self.name)
p1 = Person("Mandy", 20)
p1.myfunc()
self
是實例的代稱,用於類別中對實例方法的呼叫或屬性的引用。class BMI:
def __init__(self,name,h,w):
self.bmi = dict()
self.add(name,h,w)
def add(self,name,h,w):
self.bmi[name]={"身高":h,"體重":w,"BMI":w/(h/100)**2}
試寫一個名為BMItable
的類別,使該類別擁有紀錄人的名字、身高、體重和BMI的能力,規格如下。
class BMItable:
def __init__(self, name, high, weight):
self.bmi = dict() #{} 亦可
#TO-DO
c = BMItable("John",171,57)
c.add("Mandy",159,45)
c.add("VJ",163,48)
print (c.bmi)
#印出:
#{'John': {'身高': 171, '體重': 57, 'BMI': 19.493177387914233},
#'Mandy': {'身高': 159, '體重': 45, 'BMI': 17.799928800284796},
#'VJ': {'身高': 163, '體重': 48, 'BMI': 18.06616733787497}}
self
參數self
視作實例方法第一個傳入的引數,用於實例中方法的呼叫或屬性的引用。
不一定要命名為self
,你可以隨心所欲地調用它,但它必須是類中任何函式的第一個參數。
例如,用 mysillyobject
和 abc
兩個詞代替self
。
class Person:
def __init__(mysillyobject, name, age):
mysillyobject.name = name
mysillyobject.age = age
def myfunc(abc):
print("Hello my name is " + abc.name)
p1 = Person("John", 36)
p1.myfunc()
不過不要這麼做好嗎= =,一般來說我們還是會以self
作為傳入的那個實例的命名
Python 中類別間可以繼承–-允許我們定義一個複製另一個類別的所有方法和屬性的類別。
父類別(Parent class)是被繼承的類別,也叫基底類別。
子類別(Child class)是繼承自另一個類別的類別,也叫衍生類別。
任何類別都可以是父類別,因此語法與寫任何其他類別一樣,接下來所指的父類別都會是以下例子。
例如我們寫一個名為Person
的類別,它具有firstname
和lastname
屬性,以及一個名為printname
的方法:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
使用Person
類別構建一個物件,然後呼叫printname
方法:
x = Person("John", "Doe")
x.printname()
若要寫出一個子類別–-繼承其他類別的類別,請在寫子類別的時後將父類別作為引數傳入:
例如我們寫一個名為Student
的類別,將該類別繼承Person
的屬性和方法:
class Student(Person): pass
現在,類別Student
具有與類別Person
相同的屬性和方法。
使用類別Student
構建一個物件,然後呼叫printname
方法:
x = Student("Mike", "Olsen")
x.printname()
你也可以再使用Person 來構建,目前來說用法一樣
y = Person("John", "Doe")
y.printname()
class BMItable2(BMItable): pass
試著用名為BMItable2
的類別繼承練習 3 的BMItable
class BMItable2(BMItable):
def secret(name):
self.bmi[name]={'身高'='xxx','體重'='xxx','BMI'='xxx'}
試著用名為BMItable2
的類別繼承練習 3 的BMItable
並且新增method secret(name)
,使該name擁有的身高、體重、BMI都變成'xxx'
__init __()
函式的複寫到目前為止,我們已經成功寫了一個子類別,這個子類別是從父類別複製屬性和方法。
我們要在子類別寫__init __()
函式(而不是pass關鍵字)。
例如我們在Student
類別裡複寫__init__()
函數。
class Person:
def __init__(self, fname, lname):
#做其他事
為了保持對父類別的 __init__()
函式的繼承,可以寫成呼叫父類別的 __init__()
函式。例如:
class Student(Person):
def __init__(self, fname, lname):
Person.__init__(self, fname, lname)
super
()函式通過使用super()
函式,你不需要使用父類別的名字,它會自動繼承父類別的方法和屬性。因為需要多呼叫一個函式,雖然會慢一點,但可讀性高。
class Student(Person):
def __init__(self, fname, lname):
super().__init__(fname, lname)
class BMII(BMI):
def __init__(self,name,h,w):
BMI.__init__(self,name,h,w)
print ("這是BMII")
承上題(4.1),試著用名為BMII
的類別繼承練習 3 的BMI
後,印出
這是BMII
現在我們已經準備好 __init__()
函式了,還同時繼承了父類別,我們準備在 __init__()
函式中進行其他操作。例如我們在Student
類別中多添加一個名為graduationyear
的屬性:
class Student(Person):
def __init__(self, fname, lname):
super().__init__(fname, lname)
self.graduationyear = 108
在下面的例子中,108
會是一個變量,並在構建Student
時傳入。要做到這一點,得在__init__()
函式中多寫一個引數。添加一個year
引數,並在構建物件時傳入正確的年份:
class Student(Person):
def __init__(self, fname, lname, year):
super().__init__(fname, lname)
self.graduationyear = year
x = Student("Mandy", "Lu", 108)
class BMII(BMI):
def __init__(self,name,h,w,d):
self.bmi = d #要先定義不然放下面會覆蓋
BMI.__init__(self,name,h,w)
承上題(4.2),試著用名為BMII
的類別繼承練習 3 的BMI
後,多傳入一個dict
定義給bmi
。
d = {"VJ":{'身高': 163, '體重': 48, 'BMI': 18.07}}
c = BMII("Mandy",159,45,d)
print (d)
#印出:
#{'VJ': {'身高': 163, '體重': 48, 'BMI': 18.07},
#'Mandy': {'身高': 159, '體重': 45, 'BMI': 17.799928800284796}}
例如我們在Student
類中添加一個名為welcome
的方法。
class Student(Person):
def __init__(self, fname, lname, year):
super().__init__(fname, lname)
self.graduationyear = year
def welcome(self):
print("Welcome", self.firstname, self.lastname, "to the class of", self.graduationyear)
class BMII(BMI):
def __init__(self,name,h,w,age):
BMI.__init__(self,name,h,w))
self.bmi[name]['年齡'] = age
def add(self,name,h,w,age = None):
self.bmi[name]={"身高":h,"體重":w,"BMI":w/(h/100)**2}
if age == None: self.bmi[name]['年齡'] = age
試著用名為BMII
的類別繼承練習 3 的BMI
後,多傳入一個引數年齡。
c = BMII("VJ",162,48,21)
c.add("Mandy",159,45,20)
print (c.bmi)
#印出:
#{'VJ': {'身高': 163, '體重': 48, 'BMI': 18.06616733787497, '年齡': 21},
#'Mandy': {'身高': 159, '體重': 45, 'BMI': 17.799928800284796, 年齡': 20}}
當一個 method 是帶有 class 本身作為參數傳入時,我們稱之為 class method
class method 必須傳入 class 本身作參數,就是cls,概念跟 instance 用 self傳入instance method 的參數一樣。
class Person2: scientific_name='Homo sapiens' @classmethod def evolution(cls): cls.scientific_name = 'Hyper Homo sapiens' print(Person2.scientific_name) Person2.evolution() #使用class呼叫class mothod print(Person2.scientific_name)
其實也可以用instance 呼叫class method
class Person: year = 100 def __init__(self, height, weight): self.height = height self.weight = weight @classmethod def Kokuhaku(cls): print(f'I love Tatara {cls.year} years') Person.Kokuhaku() Yourdaughter = Person(180,100) Yourdaughter.Kokuhaku()