[英]Defining “overloaded” functions in python
我真的很喜歡“魔術方法”的語法或在Python中所謂的任何方法,例如
class foo:
def __add__(self,other): #It can be called like c = a + b
pass
通話
c = a + b
然后翻譯成
a.__add__(b)
是否可以模仿“非魔術”功能的這種行為? 在數值計算中,我需要Kronecker乘積,並且渴望具有“ kron”函數,以便
kron(a,b)
實際上是
a.kron(b)?
用例是:我有兩個相似的類,例如矩陣和向量,都具有Kronecker積。 我想打電話給他們
a = matrix()
b = matrix()
c = kron(a,b)
a = vector()
b = vector()
c = kron(a,b)
矩陣和向量類在一個.py文件中定義,因此共享公共名稱空間。 那么,實現上述功能的最佳方法(Pythonic?)是什么? 可能的解決方案:
1)具有一個kron()函數並進行類型檢查
2)具有不同的名稱空間
3)?
python默認的運算符方法( __add__
等)是硬連接的; python會尋找它們,因為操作員實現會尋找它們。
但是,沒有什么可以阻止您定義執行相同功能的kron
函數。 在傳遞給它的對象上查找__kron__
或__rkron__
:
def kron(a, b):
if hasattr(a, '__kron__'):
return a.__kron__(b)
if hasattr(b, '__rkron__'):
return b.__rkron__(a)
# Default kron implementation here
return complex_operation_on_a_and_b(a, b)
什么你所描述的是多分派或多方法 。 魔術方法是實現它們的一種方法,但是實際上,使用對象可以注冊特定於類型的實現更為常見。
例如, http://pypi.python.org/pypi/multimethod/可以讓您編寫
@multimethod(matrix, matrix)
def kron(lhs, rhs):
pass
@multimethod(vector, vector)
def kron(lhs, rhs):
pass
自己編寫多方法修飾器很容易; BDFL在一篇文章中描述了一種典型的實現。 這個想法是, multimethod
修飾器將類型簽名和方法與注冊表中的方法名稱相關聯,並用執行類型查找以找到最佳匹配的生成方法替換該方法。
從技術上講,實現類似於“標准”運算符(以及類似運算符的類,例如len()
等)的行為並不難:
def kron(a, b):
if hasattr(a, '__kron__'):
return a.__kron__(b)
elif hasattr(b, '__kron__'):
return b.__kron__(a)
else:
raise TypeError("your error message here")
現在,您只需要在相關類型上添加__kron__(self, other)
方法(假設您可以控制這些類型,或者它們不使用插槽或任何其他會阻止在類語句主體之外添加方法的方法)。
現在,我不像上面的代碼片段那樣使用__magic__
命名方案,因為這應該保留給語言本身。
另一個解決方案是維護一個type
: specifici function
映射,並讓“通用” kron
函數查找該映射,即:
# kron.py
from somewhere import Matrix, Vector
def matrix_kron(a, b):
# code here
def vector_kron(a, b):
# code here
KRON_IMPLEMENTATIONS = dict(
Matrix=matrix_kron,
Vector=vector_kron,
)
def kron(a, b):
for typ in (type(a), type(b)):
implementation = KRON_IMPLEMENTATION.get(typ, None)
if implementation:
return implementation(a, b)
else:
raise TypeError("your message here")
此解決方案無法很好地繼承,但是“少了點驚奇”-不需要Monkeypatching或__magic__
名稱等。
我認為擁有一個委派實際計算的函數是一種不錯的方法。 如果Kronecker產品僅適用於兩個相似的類,則您甚至可以在函數中進行類型檢查:
def kron(a, b):
if type(a) != type(b):
raise TypeError('expected two instances of the same class, got %s and %s'%(type(a), type(b)))
return a._kron_(b)
然后,您只需要在類上定義_kron_
方法。 這只是一些基本示例,您可能需要對其進行改進,以更優雅地處理沒有_kron_
方法的類或子類。
標准庫中的二進制操作通常具有反向對偶( __add__
和__radd__
),但是由於您的運算符僅適用於相同類型的對象,因此在這里沒有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.