前言
※ 本段有些難度,略過並不影響後續理解。
在幾天前,我實現了一個可以傳入函數呼叫的類別(Callable Class),相關可以參考「用Python實現Callable Class」。
起初,我實現Meta-Class的方式,是在defineclz.__new__(clz, *args, **kwargs)
實例(instance)後,將實例增加函數成員(Function Member)。不過這樣做並不太成功。會需要使用instance.__call__(f, *args, **kargs)
去執行。而直接複寫defineclz.__call__
的話,以會造成不斷呼叫的問題,而且無法讓後續繼承子孫,再進一步調整方法。這也是為什麼後來以內部類別實現,並且另擁有__call__
能力的類別,後於defineclz
,好讓自定義的__call__
可以複寫掉預設行為。
※ Note: 本文寫到的函數成員(Function Member),主要是指實例屬性,但這個屬性是一個函數。更多時候,成員(Member)可能就包含方法(Method)和屬性(Attribute),而函數成員(Function Member)可能就直指方法(Method)。
定義方法(method)vs定義函數(function)
※ 尚為去翻找文件,可能有錯誤。
在Python,可以用def
關鍵字去定義一個函數:
def f1():
print("call f1")
f1()
而方法的定義也是使用def
:
class C1:
class_attr1 = {}
def __init__(self):
self.instance_attr1 = {}
def _f1(self):
print("C1: f1")
def f1(self):
self._f1() # if wrote `_f1()`, it will not found
def f2(self):
def _f2():
print("C1.f2: _f2")
_f2()
c1 = C1()
c1.f1()
c1.f2()
但其實這裡就可以看出一些行為的不同。上面_f1()
和f1()
看是在同一個scope,但是如果f1()
需要呼叫_f1()
,必須使用self._f1()
或是C1._f1(self)
,如果直接寫_f1()
會報錯說找不到。相對來說f2()
是C1
類別的方法,但是內部函式_f2
不是,因此就不需要這樣寫。現在在把f1()
移出類別外,變成一般函式看看: