使用Python装饰器向方法添加方法(Using Python decorators to add a method to a method)

编程入门 行业动态 更新时间:2024-10-11 21:32:06
使用Python装饰器向方法添加方法(Using Python decorators to add a method to a method)

我希望能够根据某种标准格式调用方法:

outputs = obj.meth(in_0, in_1, ...)

,其中输出是数组的元组,每个输入是一个数组。

但是,在大多数情况下,我只返回一个数组,并且不希望为了标准格式而强制返回长度为1的元组。 (我的实际格式化问题更复杂,但现在暂时坚持这个解释。)

我希望能够定义一个类:

class _SomeClass(object): def __init__(self): self._amount_to_add = 1 @single_return_format def add_one(self, x): return x+self._amount_to_add

然后可以按如下方式调用它:

obj = _SomeClass() assert obj.add_one(3) == 4 assert obj.add_one.standard_format(3)==(4, )

问题是:如何定义装饰器以允许此行为?

我试过了:

def single_return_format(fcn): fcn.standard_format = lambda *args: (fcn(*args), ) return fcn

,但它在第二个断言的行上失败:

TypeError: add_one() takes exactly 2 arguments (1 given)

因为add_one需要“self”作为参数,并且在装饰器修改函数时甚至还没有创建对象。

那么Stack,我该怎么做?


笔记:

1)我知道我可以用基类和继承来做这件事,但是如果你想在这个方法中装饰多个方法,这就成了一个问题。

2)实际问题来自使用theano - 标准格式是outputs, updates = fcn(*inputs) ,但大多数函数不返回任何更新,因此您希望能够以自然方式定义这些函数,但是仍然可以根据此标准界面调用它们。

I want to be able to call a method according to some standard format:

outputs = obj.meth(in_0, in_1, ...)

, where outputs is a tuple of arrays, and each input is an array.

However, in most instances, I only return one array, and don't want to be forced to return a tuple of length 1 just for the sake of the standard format. (My actual formatting problem is more complicated but lets stick with this explanation for now.)

I want to be able to define a class like:

class _SomeClass(object): def __init__(self): self._amount_to_add = 1 @single_return_format def add_one(self, x): return x+self._amount_to_add

And then be able to call it as follows:

obj = _SomeClass() assert obj.add_one(3) == 4 assert obj.add_one.standard_format(3)==(4, )

Question is: how do I define the decorator to allow this behaviour?

I tried:

def single_return_format(fcn): fcn.standard_format = lambda *args: (fcn(*args), ) return fcn

, but it fails on the line with the second assert with:

TypeError: add_one() takes exactly 2 arguments (1 given)

Because the add_one requires "self" as an argument, and the the object has not even been created yet at the time the decorator modifies the function.

So Stack, how can I do this?


Notes:

1) I know I could do this with base-classes and inheritance instead, but that becomes a problem when you have more than one method in the class that you want to decorate this way.

2) The actual problem comes from using theano - the standard format is outputs, updates = fcn(*inputs), but most functions don't return any updates, so you want to be able to define those functions in a natural way, but still have the option of calling them according to this standard interface.

最满意答案

这确实是一个问题,因为从函数中检索“绑定”方法的方式不考虑这种方式。

我看到两种方式:

你可以包装函数:

def single_return_format(fcn): # TODO Do some functools.wraps here... return lambda *args, **kwargs: (fcn(*args, **kwargs), )

不要愚弄.standard_format ,但仅仅是替换功能。 所以函数可以将自己定义为返回一个值,但只能被调用为返回元组。

如果这不是你想要的,你可以定义一个用于装饰方法的类,它覆盖__get__并以“实时方式”进行包装。 当然,它也可以重新定义__call__以便它也可用于(独立的,非方法)函数。

Dunes gave the correct answer. I've stripped it down to bare bones so that it solves the problem in the question. The stripped-down code is here:

class single_return_format(object): def __init__(self, func): self._func = func def __get__(self, instance, owner): return SimpleFormMethod(instance, self._func) class SimpleFormMethod(object): def __init__(self, instance, func): self._instance = instance self._func = func def __call__(self, *args, **kwargs): return self._func(self._instance, *args, **kwargs) @property def standard_format(self): return lambda *args, **kwargs: (self._func(self._instance, *args, **kwargs), ) class _SomeClass(object): def __init__(self): self._amount_to_add = 1 @single_return_format def add_one(self, x): return x+self._amount_to_add obj = _SomeClass() assert obj.add_one(3) == 4 assert obj.add_one.standard_format(3) == (4, )

更多推荐

本文发布于:2023-07-29 05:52:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1313043.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:方法   Python   decorators   method   add

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!