簡體   English   中英

裝飾方法(類方法重載)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM