xia的小窩

一起來coding和碼字吧

0%

python-Discord-bot,從0開始到做出一個機器人系列-10

物件導向概述

物件導向程式設計(Object Oriented Programming)簡稱OOP,主要針對大型軟體設計而提出,它可以使軟體設計更加靈活。

對象

這是一個抽象的概念,世間萬物皆為對象。比如一個人。

  • 靜態被分為屬性,任何對象都具備自身屬性,如人的性別
  • 動態表示對方的行為,及對象執行的動作,孺人可以行走
  • 在Python中,一切都是對象。

類是封裝對象的屬性及行為的載體,反過來說,具有相同屬性和行為的類實體被稱為類

OOP設計特點

  1. 封裝
    將對象的屬性和行為封裝起來,而將對象的屬性和行為封裝起來的截體就是類,類通常對客戶隱藏實際細節。

  2. 繼承
    子能繼承父的特性,但無法反過來

  3. 多態
    一個父親能有多個兒子,兒子能繼承父親的技能,但兒子們也有自身的技能

定義類

在Python中,類的定義使用class關鍵字

1
2
class Classname:
statement

也可以先用pass卡著

1
2
class Geese:
pass

創建類的實例

1
classname(parameterlist)

比如,定義一個Geese類的實例

1
2
3
wildGeese = Geese()
print(wildGeese)
# <__main__.Geese object at 0x000002AD716B4DC0>

建立__init__方法

__init__是一個特殊的方法,每當創建一個新實例的時候,Pytho都會自動執行它。
__init__方法必須包含一個self參數,而且必須是第一個參數。
self參數是指象實例本身的引用,屬於訪問類的屬性和方法。
在方法要調用時會傳遞實際self參數。
因此,當__init__方法只有一個參數時,就不需要只掉參數。

1
2
3
4
5
6
7
8
9
10
class Geese:
def __init__(self):
print("我是大雁類")

wildGeese = Geese()
# 我是大雁類

# 如果把self拿掉便會出現......
# TypeError: __init__() takes 0 positional arguments but 1 was given
# 所以說還是需要self的

其實還可以自定義參數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Geese:
def __init__(self, beak, wing, claw):
print("我是大雁類")
print(beak)
print(wing)
print(claw)

beak_1 = "嘴"
wing_1 = "翅膀"
claw_1 = "爪子"
wildGeese = Geese(beak_1, wing_1, claw_1)

# 我是大雁類
# 嘴
# 翅膀
# 爪子

創建類的成員並使用

創建實例方法並使用

1
2
def funcName(self, parametetlist):
# block

創建方法完成後,可以透過類的實例名稱和”.”操作符進行呼叫

1
instanceName.functionName(parametervalue)

實際創造一個函數(fly())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Geese:
def __init__(self, beak, wing, claw):
print("我是大雁類")
#print(beak)
#print(wing)
#print(claw)
def fly(self, state):
print(state)

beak_1 = "嘴"
wing_1 = "翅膀"
claw_1 = "爪子"
wildGeese = Geese(beak_1, wing_1, claw_1)
wildGeese.fly("我可以直衝雲霄")
# 我是大雁類
# 我可以直衝雲霄

創建數據成員並使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Geese:

neck = "脖子"

def __init__(self):
print(self.neck)

geese = Geese()
# 脖子

# 此寫法等同於

self.neck = "脖子"
print(self.neck)

訪問限制

1
2
3
4
5
* _foo : 以單下滑線開頭表示protect(保護)類型的,只允許子類及本身,不能使from module import  * 語句導入。

* __foo():雙下滑線到表私有,只允許定義該方法的類本身進行訪問,可以透過"類的實例名.類名.__xxx"方式訪問。

* __foo__():代表特殊定義方法,一般表示系統定義名字,比如:__init__()

屬性

建立用於計算的屬性

1
2
3
@property
def methodname(self):
block

實際運用

1
2
3
4
5
6
7
8
9
10
11
class Reat:
def __init__(self, width, height):
self.width = width
self.height = height

@property
def area(self):
return self.width * self.height

print(Reat(100, 200).area)
# 2000

轉化成屬性後,就可以直接透過方法名來訪問方法,就不需要添加小括號

添加安全保護機制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 想要建立可以讀取但不能相改的屬性可以用@property實踐
class TVshow:
def __init__(self, show) :
self.__show = show

@property
def show(self):
return self.__show

tsShow = TVshow("正在播放<<8964>>")
print("默認: ", tsShow.show)
# 默認: 正在播放<<8964>>
# 那如果改成...

# tsShow = "正在播放<<爆打粉紅>>" 修改屬性值
# print("修改後: ", tsShow.show) 獲取屬性值

# AttributeError: 'str' object has no attribute 'show'

繼承

簡單明瞭,就是繼承父類

1
2
class className(baseclasslist):
Statement

比如說….

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class fruit:
color = "green"

def fruitcolor(self, color):
print("水果顏色是: ", color)
print("-----------")
print("原本的顏色是: ", fruit.color)

class Apple(fruit):
color = "red"

def __init__(self):
print("我是蘋果")

Apple().fruitcolor(Apple.color)

# 我是蘋果
# 水果顏色是: red
# -----------
# 原本的顏色是: green

方法重寫

在自身認為不適用的情況下,對def內部的函式內容作改寫。

使用super()呼叫父類

如果要在子類中引用父類的方法,但是又需要新增一些子類所特有的內容,可通過類名.方法()和super()來呼叫父類的方法,再個性化子類的對應函式。
直接使用類名.方法()來呼叫時,還是需要傳入self為第一個引數,而使用super()呼叫則python自動將self傳入,因此使用super()比較簡潔。

這邊有兩點好處

  1. 簡化程式碼
  2. 如果父類名稱修改,對其他呼叫父類函式的類來說也沒有影響,而如果直接使用父類的名稱來呼叫,父類名稱修改會影響其他所有的類。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class drive:
def __init__(self, name):
self.name = name
def getname(self):
return self.name
def displayVehicle(self):
print("廠牌: ", self.name)

class car(drive):
def __init__(self, name, mod):
super().__init__(name) # 呼叫父類建構函式
self.mod = mod
def display(self):
print(self.getname())
print(self.mod)

drive("BMV").displayVehicle()
car("totya", "GH333").display()
# 廠牌: BMV
# totya
# GH333