如標題,紀錄一下 python 中有幾個基礎的東西。
__init__ 和 __call__ 是 Python 中特別定義的類方法,它們屬於一類稱為 "魔術方法"(magic methods)或 "特殊方法"(special methods)的方法。這些方法有特定的命名規則(以雙下劃線開始和結束)和特定的功能。
1. __init__ 方法:
- __init__ 是一個初始化器(不是構造函數,Python 的構造函數是 __new__,參考下方補充。)。
- 當創建類的新實例時,__init__ 會自動被調用。
- 它用於設置對象的初始狀態或初始化其屬性。
- 這是一個非常常用的方法,用於類的任何初始化操作。
- 只能定義一個,若有多個,只有最後一個定義的會被使用。
2. __call__ 方法:
- __call__ 方法使得實例能夠被當作函數來調用。
- 當實例被當作函數調用時(即像 instance() 這樣),Python 會自動調用該實例的 __call__ 方法。
- 這個方法的使用在某些情況下非常方便,尤其是在設計像函數一樣行為的對象時。
- 只能定義一個,若要處理多種情況,使用條件語句來檢查傳入參數的類型或數量,或者使用可變參數(如 *args 和 **kwargs)來處理不同的參數情況。
範例: 建立一個Greeter的類,並且實例化、調用方法。
code: python
# 建立一個Greeter的類
class Greeter:
# 定義
def __init__(self, name):
self.name = name # 使用 __init__ 方法初始化 name 屬性
def __call__(self, greet):
return f"{greet}, {self.name}!" # 定義 __call__ 方法,使實例可以被調用
code: python
# 初始化 Greeter 實例
# 創建了一個 Greeter 的實例,將 "Alice" 作為名字傳入。這個名字通過 __init__ 方法設置到實例的 name 屬性上。
greeter = Greeter("Alice")
code: python
# 調用實例方法
# 然後我使用這個實例就像調用一個函數那樣,傳入一個問候語 "Hello"。由於實例有 __call__ 方法,所以它可以被像函數那樣調用。
# __call__ 方法接收這個問候語並返回一個格式化的字符串。
greeting_message = greeter("Hello") # 調用實例,返回 "Hello, Alice!"
總結:
以上這個例子通過 __init__ 方法設置初始狀態(在這裡是設置名字),並通過 __call__ 方法使得實例的行為像一個函數。這種方式在編寫具有函數特性的類時非常有用。
補充:
- 關於 __new__:
在 Python 中,__new__ 是一個特殊的靜態方法,用於創建並返回一個類的新實例。它是在 __init__ 方法之前被調用的,並且是真正的構造函數。然而,在日常 Python 編程中,__new__ 的使用並不常見。它主要在涉及到較為復雜的對象創建過程,或者在創建不可變的數據類型(如 int、str、tuple 等)的子類時才會用到。
# 在這個範例中,Singleton 類使用 __new__ 方法來確保類的實例只被創建一次。
# 每次嘗試創建 Singleton 的新實例時,__new__ 方法都會先檢查是否已經存在一個實例,如果存在,則返回那個已經存在的實例。
code: python
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
def __init__(self):
self.value = "Some state"
# 現在,無論你創建多少次 Singleton 的實例,它都只會有一個實例存在。
singleton1 = Singleton()
singleton2 = Singleton()
print(singleton1 == singleton2) # 這將輸出 True,因為兩個變數引用的是同一個實例。
總的來說,除非你需要控制對象的創建過程(例如實現設計模式如單例模式),否則在日常的 Python 編程中很少需要使用 __new__。大多數時候,只使用 __init__ 方法就足夠了。
- 可變參數(*args, **kwargs):
code: python
# 創建了一個名為 FlexibleGreeter 的類,它演示了如何在 __call__ 方法中使用 可變參數(*args)和關鍵字參數(**kwargs)
# 定義 迎接人員 Class
class FlexibleGreeter:
# 定義初始方法,設定招呼用語。
def __init__(self, greeting):
self.greeting = greeting
# 定義實例方法,取得完整招呼。
def __call__(self, *args, **kwargs):
# 取得 關鍵字參數 **kwargs
# 若沒有取得任何參數,預設給 there
name = kwargs.get('name', 'there')
# 取得 可變參數
if args:
# 對傳入的可變參數,進行 'and' 字串組合
name = ' and '.join(args)
# 返回 完整招呼。
# 在3.6+版本,可以使用 f-string 字串插入語法 {XXXX},進行高效的字串組合
return f"{self.greeting}, {name}!"
# 實例化 迎接人員
greeter = FlexibleGreeter("Hello")
# 以下使用實例方法
# 使用 關鍵字參數 **kwargs。 (name="Alice")
greeting1 = greeter(name="Alice") # 'Hello, Alice!'
# 使用 可變參數 *args。 ("Alice", "Bob")
greeting2 = greeter("Alice", "Bob") # 'Hello, Alice and Bob!'
# 不使用參數
greeting3 = greeter() # 'Hello, there!'