gpt4 book ai didi

python - 装饰方法(类方法重载)

转载 作者:太空狗 更新时间:2023-10-30 02:49:53 25 4
gpt4 key购买 nike

灵感来自 Muhammad Alkarouri 在 What are good uses for Python3's "Function Annotations" 中的回答,我想为方法而不是常规函数执行此 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)

这似乎是意料之中的,如 Decorating a method 中所解释的那样,因为 self 参数。

但我不知道如何让它发挥作用。好吧,当我删除“ self ”时,它(几乎)工作正常,但我不想删除它。请注意,我这样做是为了练习,我知道有一些库提供方法重载。

我尝试过的:

  • 非常愚蠢,但想尝试 - 在 def multimethod( function ) 中添加参数 self - 同样的错误

  • 我想在 class MultiMethod__init__ 中添加第三个参数 - obj 并存储 self 作为成员,但我无法通过 multimethod 执行此操作,因为它是一个函数。

  • 我不想为装饰器添加参数,所以这个选项(如果可能的话)被忽略

我读了几个类似的问题,但没有找到我要找的东西。我很确定这是个伪问题,但我已经没有想法了。

最佳答案

您遇到的基本问题是您使用类代替函数。没有将该类绑定(bind)到调用它的实例的机制,这与自动发生的函数不同。

简而言之,当您执行 a.foo( .. ) 时,它会返回一个 MultiMethod,但是这个对象并不知道它应该绑定(bind)到 一个

您必须以某种方式传入实例。一种简单的方法是将它全部包装在一个函数中,然后让 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 ) )

更复杂的方法是在执行此绑定(bind)的 A 类上编写您自己的描述符。

关于python - 装饰方法(类方法重载),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6009344/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com