owned this note
owned this note
Published
Linked with GitHub
###### tags: `Python`
# Class
**<a href="https://hackmd.io/@Mes/python_note" class="redlink">點此回到 Python筆記 目錄</a>**
# 前言
當一些資料有關連性時我們可以使用 List 把它包在一起,但這種方法通常會在資料能夠全部列出來,並且資料本身並不複雜的時候使用,像是之前買課本的範例,List 內只有 課本名稱 和 課本數量,並且我們知道了課本有國英數自社這五種。那假設我們今天並不知道有哪些課本需要購買的話怎麼辦呢?
# 語法
這時候我們就需要 Class 了,Class 的概念像是一個設計藍圖,會預先把相關的資料與函式的「格式」給寫好,以上方的例子來說,會有一個藍圖(Class) 叫做「課本」,藍圖裡面要規定一些內容,像是課本的名稱、課本的數量、課本的價錢等等。 那我們可以這樣做:
```python=
class Book :
def __init__(self, name, money, quantity):
self.name = name
self.money = money
self.quantity = quantity
def printing(self):
print("您購買了", self.quantity, "本", self.name)
print("一共要", self.quantity * self.money, "元")
print()
chinese = Book("國文課本", 200, 5)
english = Book("英文課本", 300, 4)
math = Book("數學課本", 400, 3)
chinese.printing()
english.printing()
math.printing()
```
在上方的例子中,我們創了一種 Class 叫做 Book,Book 預設會有3種值,分別為名字、錢和數量,另外在 Class 內我們定義了一個函式叫做 `printing()` ,用來把金額給印出來。
再來我們看它的語法,首先會有 `class` 關鍵字,後方會接這個 Class 的名稱, Class 的名字我們通常第一個字會大寫,後面記得要冒號。
Class 內一定會要定義一個函式叫做 `__init__` ,這個函式的意義是初始化這個Class的值,我們有給這個函式取一個名字,叫做建構子。 這樣一來我們就畫出了一種書的「藍圖」,它告訴我們每本書都要有名字、價格和數量,並且都能夠印出金額。 之後在主程式中,我們創了變數來接受這個 Class 實作出來的東西,像是 `Book("國文課本", 200, 5)` 代表這本書是國文課本,價格是200元,然後我們要買5本,如此一來透過 `__init__` 我們就能夠初始化這個實作出來的東西的值了。
另外,利用 Class 實作出來的東西我們會稱它為 「物件」,以上例來說,`chinese`、`english` 和 `math` 都是物件,因為他們都是透過 Class 實作出來的東西。
現在我們既然利用這個藍圖製造出了一個實際的物件,那我們就可以試試看藍圖裡面寫好的功能,以上例來說就是 `printing()` ,在主程式最下方的三行能夠看到我們呼叫了這三個物件本身的 `printing()`
# 訪問許可權限 (public、private 與 protect)
在上例中我們可以透過這樣來呼叫出每個物件裡面儲存的值:
```python=
print(chinese.name)
print(english.name)
print(math.name)
```
有時候我們並不想要這樣,因為 Class 在設計的時候我們都已經寫好它的功能了,如果要改物件裡面的值,我們通常會希望是透過我們寫好的功能來改,而不是可以直接這樣呼叫它來改,這種能夠在外面呼叫物件裡面的值,我們會稱它的訪問權限為 `public` ,意思是它是一個公開的值。
如果要避免上方這種狀況發生,我們可以在設計 Class 時,在裡面的變數前加上 `__` ,表示我們無法從外面呼叫它,只能在 Class 裡面呼叫它:
```python=
class Book :
def __init__(self, name, money, quantity):
self.__name = name
self.__money = money
self.__quantity = quantity
def printing(self):
print("您購買了", self.__quantity, "本", self.__name)
print("一共要", self.__quantity * self.__money, "元")
print()
```
如此一來,我們就無法在主程式內呼叫物件裡儲存的東西了,因此下方這樣會噴錯:
```python=
print(chinese.__name)
print(english.__name)
print(math.__name)
```
而透過 Class 設計好的方法我們仍然能呼叫它:
```python=
chinese.printing()
english.printing()
math.printing()
```
這種變數我們就會稱它的訪問權限為 `private` ,意思是它是一個私有的的值,只能在 Class 內使用,也就是說只有在 Class 裡面設計功能時能呼叫它,像是上例 `printing()` 內就呼叫了 `__name` 等變數,但其實 Python 並沒有分 Private 和 Public,詳細的底層大家可以自己去看。
然而無法從外面呼叫有時也是個壞處,但我們又不想讓使用者如此容易的呼叫它,因此我們這時就會在變數名稱前方加上一個底線 `_` ,表示它是一個能從外面呼叫的值,但是記得要小心可能會有風險,例如不小心改到物件內容等等,這樣的訪問權限我們稱它為 `protect` ,代表它是一個受保護的值,從外面呼叫它的時候要注意一下。
# 練習
### 練習1:利用 Class 做出一個時鐘
> 提示:可以引用函式庫 `time` 裡的 `sleep` 函式,`time.sleep(數字)` 代表程式會停頓我們填入的數字的秒數後再繼續執行。
參考解答:
```python=
from time import sleep
class Clock :
def __init__(self, hour = 0, minute = 0, second = 0):
self._hour = hour
self._minute = minute
self._second = second
# 運作的函式
def run(self):
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
# 顯示的函式
def show(self):
return f"{self._hour:02d}:{self._minute:02d}:{self._second:02d}"
clock = Clock(00, 00, 00)
while True:
print( clock.show() )
sleep(1) # 停頓一秒
clock.run() # 秒數+1
```
# 額外文章
我們基礎的語法基本上就教到這裡了,其實 Class 還有很多東西,但因為那比較偏向程式風格了,所以我們這次的課就不討論到這麼後面,那我這邊會貼幾篇文章,有興趣的可以去看看。
<br>
Class 在使用的時候可能還會有繼承關係,也就是說我們的藍圖是有層次的,像是製作一個「老師」的 Class ,那我們設計的方式可能會是「人類」 -> 「老師」,也就是說「老師」這個設計圖要利用到「人類」這個設計圖,此時我們就會需要繼承了,有興趣的可以看看課本:
<strong><a href = "https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/09.%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E8%BF%9B%E9%98%B6.md" class = "redlink">09.面向對象進階</a></strong>
<strong><a href = "https://openhome.cc/Gossip/Python/index.html" class = "redlink">語言技術:Python Gossip</a></strong>
<br>
在設計 Class 的時候我們可能會用到裝飾器,裝飾器是一個好用的工具,能幫助我們有效的化簡程式,有興趣的可以看看課本和這篇:
<strong><a href = "https://medium.com/citycoddee/python%E9%80%B2%E9%9A%8E%E6%8A%80%E5%B7%A7-3-%E7%A5%9E%E5%A5%87%E5%8F%88%E7%BE%8E%E5%A5%BD%E7%9A%84-decorator-%E5%97%B7%E5%97%9A-6559edc87bc0" class = "redlink">Python進階技巧 (3) — 神奇又美好的 Decorator</a></strong>
<style>
.green {
color:#29E5A9;
}
.brown {
color:#990000;
}
.pink {
color:#C18387;
}
.red {
color:#E71B18 ;
}
.blue {
color:#0b5394;
}
.purple {
color:#AC9FDD;
}
@-webkit-keyframes A
{
0% { color:#C10066;}
10% { color: #CC0000;}
20% { color: #E63F00; }
30% { color:#EE7700; }
40% { color: #DDAA00; }
50% { color:#EEEE00;}
60% { color: #99DD00;}
70% { color:#66DD00;}
80% { color: #00DDDD;}
90% { color: #0044BB;}
100% { color: #A500CC;}
}
#animation_title{
animation: A 3s ease 0s infinite alternate;
-webkit-animation: A 3s ease 0s infinite alternate;
}
</style>
<style>
a.redlink {
color:#DF2F6A;
}
a.redlink:link {
color:#DF2F6A;
text-decoration:none;
}
a.redlink:visiteid {
color:#DF2F6A;
text-decoration:none;
}
a.redlink:hover {
color:#19CABC;
text-decoration:none;
}
a.redlink:active {
color:#000000;
text-decoration:underline;
background:#FFFFFF;
}
</style>
<style type="text/css">
h1 {
font-size:;
color:#0b5394;
}
h2 {
font-size:;
color:#0b5394;
}
p {
font-size:;
color:;
}
h3 {
font-size: ;
color:#990000;
}
h4 {
font-size:;
color:#990000;
}
</style>