- 登入
- 註冊
Python 理財的初學者隨著程式越寫越多,應該會越來越常碰到幾種情況:
「啊!這個之前寫過,複製貼過來好了」這時候通常第一個會想到要使用的是定義 def 函數,來解決重複使用同一段程式碼的狀況。對 def 不熟的讀者可以先看之前的文章:函式 def 把重複的動作包裝起來!
然後隨著 def 越來越多、程式越來越複雜,「物件導向」的開發方式是一種常見的做法,在 Python 主軸就是圍繞在 class 類別和物件的概念了!
「物件」是什麼呢?舉個最簡單的例子,我們在模擬或是回測的時候要假設一個虛擬的帳戶。這個帳戶就像「存摺」一樣,保存了每筆買賣和轉帳紀錄,如果要計算某段期間的損益,從存摺中查看就能算出來。
在這個情況,定義一個帳戶的類別似乎是個不錯的主意!因為,如果你正在模擬把兩支策略運行在各自的帳戶,但又想要綜合檢驗投資成效,只要用類別 class 定義「存摺」的範本,然後用這個範本創造兩本「存摺物件」,就可以讓整個程式的邏輯變得更清晰易懂。
於是,我們接下來就用這個例子來做 class 的解說吧!
這個例子裡,我們定義了一個 class 叫做 Account。
class Account:
def __init__(self, balance: float = 0.0, password: str = ""):
self.balance = balance
self.position = {}
self.__password = password
self.log = []
def deposit(self, amount: float):
self.balance += amount
self.__save_log({"type":"deposit","amount":amount})
def withdraw(self, amount: float):
if self.balance >= amount:
self.balance -= amount
self.__save_log({"type":"withdraw","amount":amount})
else:
print("balance insufficient!")
def check_password(self, pw):
return True if pw == self.__password else False
def __save_log(self, log):
self.log.append(log)
首先是 def __init__ 的部分,這是在我們創造這個 class 的物件時,會直接運行的函數,概念上是在初始化這個物件。而後接續的括弧是創造物件時必須傳入的參數。程式碼撰寫方式如下:
def__init__(self, 變數名稱: 預設資料型態 = 預設值, …)
依照上面的例子,我們希望在 Account 物件被創造時,要傳入初始的帳戶餘額 balance,資料型態為 float 浮點數、預設值為 0,以及傳入初始的帳戶密碼 password,資料型態為 str 字串、預設值為 “” 空字串。
在 __init__ 初始化函數內,我們把剛剛傳入的帳戶餘額和密碼存成物件的屬性,因此可以看到變數前面加了 self.,表示我們定義了這個「帳戶」的範本,它必須有這幾個屬性。除此之外,我們還定義了一個屬性叫做 position,就像證券存摺一樣,它也管理著你的股票部位,初始值為空的字典,表示帳戶裡沒有股票持倉。
眼尖的讀者應該有一個疑惑,為什麼我要把密碼定義成 self.__password 呢?在 Python 這叫做 private 私有術性。簡單來說,從外部無法直接取用這個屬性。(其實在 Python 這有破解方法,這裡先不提)。無法直接取用是什麼意思呢?這裡舉個例子:
# 首先,創造一個物件 account(開一個帳戶)
# 初始存入 10000 元,並設密碼為 example
account = Account(10000, “example”)
# 如果想創造另一個帳戶,依樣畫葫蘆就行了
account2 = Account(100, “example_2)
print(account.balance) # 印出結果 10000
print(account.__password)
# 出現錯誤 AttributeError: 'Account' object has no attribute '__password'
那要如何取用呢?要透過像範例裡的 check_password 函數一樣,從內部取用。所以,這時候如果我輸入以下程式碼是沒問題的!
account.check_password("example") # 回傳值為 True
另外,能夠舉一反三的同學,應該能看出,def __save_log 也帶著私有屬性!所以我不能從外部寫入帳戶紀錄 log,只能在存款(deposit 函數)和提款(withdraw 函數)時,從內部調用它。(當然這不包括破解私有屬性的情況)
實例方法 instance method:以 self 為開頭,傳入物件
上面這些函數,都是最典型、最常用的實例方法,傳入參數第一個為 self,在創造物件後,透過物件自己去呼叫。舉例來說,我們要存入 100 元的話,應該這麼寫:
account = Account(10000, “example”) # 創造物件
account account.deposit(100) # 存入 100 元,呼叫時只需傳入 self 之後的參數
靜態方法 staticmethod:大家都能取用的方法
另外,之前收到讀者訊問說,如果我想讓人人都能調用 class 裡面的 def,用 class 來管理,要怎麼寫?
Python 能夠實現這個情境,不過有一些小撇步要注意!我們接續著前面的例子做說明。假設我們把下面這個函數「取得系統維護時間」也定義在上面的 class Account 之中:
@staticmethod
def get_maintenance_time():
return "Sunday 4:00 ~ 5:00 AM"
這時候,無論是用物件呼叫,還是不先實例化,直接用類別取用,都是沒問題的!程式碼如下:
# 以物件呼叫
account = Account(10000, “example) # 創造物件 account
print(account.get_maintenance_time()) # 印出結果: "Sunday 4:00 ~ 5:00 AM"
# 直接取用(注意 Account 是 class 名稱,開頭變成大寫了!)
print(Account.get_maintenance_time()) # 一樣能印出結果: "Sunday 4:00 ~ 5:00 AM"
class 入門先講到這邊,撰寫 Python 理財會用到的 class 並不會太深,若有需要,後續我們再補充吧!