[英]Decorating method (class methods overloading)
受Muhammad Alkarouri的啟發,回答Python3的“功能注釋”有什么用處 ,我想對方法做multimethod
方法,而不是常規功能。 但是,當我這樣做
registry = {}
class MultiMethod(object):
def __init__(self, name):
self.name = name
self.typemap = {}
def __call__(self, *args):
types = tuple(arg.__class__ for arg in args) # a generator expression!
function = self.typemap.get(types)
if function is None:
raise TypeError("no match")
return function(*args)
def register(self, types, function):
if types in self.typemap:
raise TypeError("duplicate registration")
self.typemap[types] = function
def multimethod(function):
name = function.__name__
mm = registry.get(name)
if mm is None:
mm = registry[name] = MultiMethod(name)
types = tuple(function.__annotations__.values())
mm.register(types, function)
return mm
class A:
@multimethod
def foo(self, a: int):
return "an int"
a = A()
print( a.foo( 1 ) )
我懂了:
Traceback (most recent call last):
File "test.py", line 33, in <module>
print( a.foo( 1 ) )
File "test.py", line 12, in __call__
return function(*args)
TypeError: foo() takes exactly 2 arguments (1 given)
由於self
論證,正如裝飾方法中所解釋的那樣,這似乎是預期的。
但我不知道如何讓它發揮作用。 好吧,當我刪除“自我”時,它工作(幾乎)很好,但我不想刪除它。 請注意,我正在練習這個,我知道有一些libs,提供方法重載。
我嘗試了什么:
非常愚蠢,但想嘗試 - 在def multimethod( function )
添加參數self
- 同樣的錯誤
我想在class MultiMethod
的__init__
中添加第三個參數 - obj
並將self
存儲為成員,但是我不能通過multimethod
這樣做,因為它是一個函數。
我不想為裝飾器添加參數,因此忽略了這些選項(如果可能的話)
我讀了幾個類似的問題,但沒找到我要找的東西。 我很確定這是一個虛假的問題,但我沒有想法。
您遇到的基本問題是您使用類來代替函數。 沒有機制將該類綁定到它調用的實例,這與自動發生的函數不同。
簡而言之,當你執行a.foo( .. )
它會返回一個MultiMethod
,但是這個對象不知道它應該綁定到a
。
您必須以某種方式傳遞實例。 一種簡單的方法是將它全部包裝在一個函數中,讓Python做到這一點:
registry = {}
class MultiMethod(object):
def __init__(self, name):
self.name = name
self.typemap = {}
# self = a MultiMethod instance, instance = the object we want to bind to
def __call__(self, instance, *args):
types = tuple(arg.__class__ for arg in args) # a generator expression!
function = self.typemap.get(types)
if function is None:
raise TypeError("no match")
return function(instance, *args)
def register(self, types, function):
if types in self.typemap:
raise TypeError("duplicate registration")
self.typemap[types] = function
def multimethod(function):
name = function.__name__
mm = registry.get(name)
if mm is None:
mm = registry[name] = MultiMethod(name)
types = tuple(function.__annotations__.values())
mm.register(types, function)
# return a function instead of a object - Python binds this automatically
def getter(instance, *args, **kwargs):
return mm(instance, *args, **kwargs)
return getter
class A:
@multimethod
def foo(self, a: int):
return "an int", a
a = A()
print( a.foo( 1 ) )
更復雜的方法是在執行此綁定的A
類上編寫自己的描述符。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.