---
lang: zh-tw
tags: Python
title: 類別與物件(入門版) - Python 教學
description: 中興大學資訊研究社1101學期程式分享會主題社課
image: none
---
###### [Python 教學/](https://hackmd.io/7-LP9CyOThOdkEbq44FLvw)
# 類別與物件(入門版)
> [name=Hui][time= 110,12,9]
>
根據我朋友的意見,這邊可能會有點難以理解
如果觀看時有任何不適,包含噁心、頭暈目眩、無法理解,請立即舉手反映
另外,有些地方可能會有一點點的不精準,那是為了方便各位理解還請見諒
## 物件導向觀念
Python是一種物件導向的程式語言。在Python中,幾乎所有的東西都是一個物件(object)。
包含function本身也是
```python=
def foo():
print(hellow)
print(type(foo)) #印出foo 是甚麼東西
print(dir(foo)) #印出foo 裡有甚麼東西
```
output
```
<class 'function'>
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
```
一個物件最主要的組成即是**屬性(Attribute)**和**方法(Method)**
>另外你看到所有有兩個底線的東西都是預設值,初學不用理會即可
#### 練習1
請印出**list**中的所有成員(Attributes and Methods),並觀察之
>hint: use dir()
### 類別(class)
類別(class)就像構建物件的「藍圖」,或者說是一個構建物件的函式。
另外,物件中的方法(Method)是指在物件裡的函式,物件中的屬性(
Attributes)是指物件裡的變數。
>Method: 舉個例來說,我們常用的list.append() 就是list的Method
>Attributes: 物件裡的變數
### 實例(instance)
如果類別是藍圖的話,那instance就是實體啦,也就是object本身。同一個class 的不同instance是彼此獨立的(當然也有方法讓他們共享某些資料)
而在python 中可以使用函式"isinstance"來檢查是否為該class的實例
>isinstance(obj,class) # True if object is the instance of the class else False
如
```python=
l = [1,2,3]
print(isinstance(l,list))
#>>> True
```
```python=
dic = {'a':'apple','b':'ball'}
print(isinstance(dic,dict))
#>>> True
```
### 名稱
名稱與別名的問題我們在使用list常常遇到,如下面範例
```python=
a=[1,2,3]
b=a
a.append(4)
print(a)
#>>> [1, 2, 3, 4]
print(b)
#>>> [1, 2, 3, 4]
print(a is b)
#>>> True
```
我們可以得知a 實際上跟b是同一個東西
>使用"is"來檢查是否為同一個物件
詳見:https://docs.python.org/zh-tw/3/tutorial/classes.html#a-word-about-names-and-objects
#### 練習2
```python=
a = [1,2,3,4]
b = [1,2,3,4]
print(a == b) #Q1
print(a is b) #Q2
```
請回答 Q1、Q2分別會印出甚麼?
#### 補充
如果想要複製一份list,而不是表示同一份list的話請使用
```python=
a=[1,2,3]
b = a[:] #用法1
c = a.copy() #用法2
print(a,b,c)
#>>> [1,2,3][1,2,3][1,2,3]
a.append(4)
print(a,b,c)
#>>> [1,2,3,4][1,2,3][1,2,3]
```
# 實際練習
還記得上次教的函式庫嗎?
這次我們用 datetime 作為範例來講解以下行為
說明文件:https://docs.python.org/zh-tw/3/library/datetime.html
```python=
import datetime
```
我們先來看看這個模組都提供了些甚麼東西吧
```python=
help(datetime)
```
節錄
```
...
CLASSES
builtins.object
date
datetime
time
timedelta
tzinfo
timezone
...
```
或者你可以點開上面網址
找到

這些都是這個模組提供的類別(class)
## 建立(初始化)
**我們以datetime中的date為例**
### 建構子
按圖施工
我們要建立一個class的instance,必須按照class規定的方法。
另外這個建立instance的"方法",我們稱之為建構子,他的呼叫方式就是class自身的名子
>就有點像你要用原料去製造一個東西一樣,那建構子就是製造這個東西的方法
找到說明文件的下面對於date物說明的地方

這是最基礎的建構方法,之後其他的建構方法都是基於此方法延伸出來的
我們觀察一下
>class datetime.date(year, month, day)
>
在上列程式碼的描述中date後面直接放參數,表示他是建構子,需要建立date物件時直接呼叫即可

試試看下列程式碼
```python=
import datetime
this_day = datetime.date(2021,12,9)
print(this_day)
```
#### 練習3
建立一個 **2022年11月16日** 的 **date** 物件
### 延伸方法
而在此基礎上,通常一個class也會提供建立特定物件的方法,例如**date**這個類別提供了[這些](https://docs.python.org/zh-tw/3/library/datetime.html#date-objects)方法來建立物件。
我們以**today**為例
```python=
import datetime
this_day = datetime.date.today()
print(this_day)
#>>> 2021-12-09
```
#### 練習4
使用"2022-11-16"來建立**date**物件
>hint: 去剛剛[那個](https://docs.python.org/zh-tw/3/library/datetime.html#date-objects)網頁找找看有沒有支援的方法
## 屬性(Attribute)
**date** 裡面提供了三個屬性(不包含預設的)

看到有藍色磚塊的那ㄍ,那個就是了
```python=
import datetime
this_day = datetime.date.today()
print(this_day.year)
#>>> 2021
print(this_day.month)
#>>> 12
print(this_day.day)
#>>> 9
```
### 練習5
承練習4,請印出該物件的日期
>2022年11月16日
### 練習6
計算生命靈數計算機
>生命靈數怎麼算? 將你的西元出生年月日全部數字加總,如果得出的是二位數,此兩數再相加,直到成為個位數字,即可得到你的生命靈數,也可以知道你是屬於幾號人(共1-9號人)。 2+2=『4』→此為你的生命靈數哦!
>如 2000年 11月 11日則為 2+0+0+0+1+1+1+1 = 6
>-by google
給定一個datetime.date物件,請補全下列function以回傳生命靈數
```python=
import datetime
def magicLifeNumber(birthday: datetime.date) -> int:
# to do .....
```
>hint1: 請注意datetime.date 中各屬性的型別
>hint2:
>使用下方程式碼以檢查你的答案是否正確(會印出5)
>test_birthday = datetime.date(1999,11,29)
print(magicLifeNumber(test_birthday))
::: spoiler **Answer**
```python=
def magicLifeNumber(birthday: datetime.date) -> int:
birthday_string = str(birthday.year) + str(birthday.month) + str(birthday.day)
while (len(birthday_string) >= 2):
temp = 0
for c in birthday_string:
temp += int(c)
birthday_string = str(temp)
return temp
```
:::
## 方法(Method)
>這邊我們暫時只探討實例方法(instance method)
物件的方法為物件的function,是可呼叫的
並且是物件提供我們對物件的操作手段,或是藉由物件的屬性延伸的以資料(例如剛剛的生命靈數函示)
例如list.append()就是list提供的方法
下面我們將繼續以datime.date作為例子
一樣我們看到[這邊](https://docs.python.org/zh-tw/3/library/datetime.html#date-objects)
根據這段描述

```python=
import datetime
this_day = datetime.date.today()
print(this_day)
#>>> 2021-12-9
another_day = this_day.replace(year=2022)
print(another_day)
#>>> 2022-12-9
```
another_day 則為一個新的datetime.date物件,並擁有屬性
year=2022,month=12,day=9
還有一些有趣的,例如
```python=
import datetime
this_day = datetime.date.today()
print(this_day.isoweekday())# 今天禮拜4
```
#### 練習7
查看datetime.date的說明
找到方法使用上面的**this_day**印出
>Thu Dec 9 00:00:00 2021
>hint 方法是需要透過呼叫的,記得加小括號
## 繼承
以剛剛datetime.date 為例,我們在表示日期時常常也會需要表示時間
那怎麼辦呢?
難不成只有日期時使用這份code,加上時間的話我們要再寫另一份code?
這時候我們就會用到繼承啦!
在**datetime**這個模組中,還有另一個class叫**datetime**(datetime.datetime)
```python=
import datetime
this_day = datetime.datetime.now()
print(this_day)
#>>> 2021-12-09 09:47:22.154680
```
他在日期的基礎上又多加上了時間的功能,換而言之
**datetime.date**繼承了**datetime.datetime**
datetime.datetime 為父類別
datetime.date 為子類別
### 特性
繼承的特性是父類別的所有成員(屬性與方法),子類別通通都要有,而且名稱必須一樣
當某個功能需要使用父類別時,那完全可以使用子類別來代替
例如:

繼承

當有人需要紅筆時,你完全可以拿上面那支筆給他
#### 練習8
複製練習6的答案,並傳入一個datetime.datetime的物件進去,觀察程式的情況
## 補充
### 反射(reflex)
reflex 顧名思義是要先照到物體才會有反光
在程式語言中,我們會用於檢查物件
如dir(), type() 等等,希望由物件來自己告訴我們她的特徵
### 預設屬性
python 中的所有物件都是繼承baseobject中而來,所以有些屬性是已經存在的,在命名上,一般會在前後各家兩個底線
(\_\_xx\_\_)
使用dir()看到的就是這些
並且同時是readonly
### print
其實我們在使用print(obj)時,就是在調用obj.\_\_str\_\_(),由它的回傳字串來決定螢幕上印的東西
當你需要該物支援該物件在螢幕上的列印時修改她即可
```python=
class hyper_datetime(datetime.datetime):
def __str__(self):
return self.ctime()
a_day = hyper_datetime.now()
print(a_day)
```