装饰类方法的pythonic方式
pythonic way of decorating classmethods
给定以下示例:
class A:
def f(self, x):
return 2*x
我想写另一个方法,它使用上面的 f
但添加一个常量,即
class A:
def f(self, x):
return 2*x
def g(self, x):
return self.f(x) + 10
这是一种方式。然而,这闻起来很像装修!执行此操作的正确 pythonic 方法是什么?
你可以在class外写一个简单的函数:
def add_val(f):
def wrapper(cls, _x):
return f(cls, _x) + 10
return wrapper
class A:
@add_val
def f(self, x):
return 2*x
print(A().f(20))
输出:
50
编辑:您可以在 Python3 中使用 functools.wraps
和 classmethod
。包装函数 f
将 return x*2
并且装饰器 g
会将 10
添加到传递给它的函数的 returned 结果。但是,为了能够保存 f
的原始功能,您可以利用 __wrapped__
属性:
import functools
def g(f):
@functools.wraps(f)
def wrapper(cls, _x):
return f(cls, _x)+10
return wrapper
class A:
@classmethod
@g
def f(cls, x):
return x*2
f_1 = functools.partial(A.f.__wrapped__, A)
print(A.f(4))
print(f_1(4))
输出:
18
8
@Ajax1234 的扩展答案,您可以尝试:
- 参数化你的装饰器,
- 显式调用你的装饰器(没有 @
)。
def add_val(_value):
def decorator(f):
def wrapper(cls, _x):
return f(cls, _x) + _value
return wrapper
return decorator
class A:
def f(self, x):
return 2*x
g = add_val(10)(f)
[编辑]
您还可以使用 functools.wraps()
改进装饰器(它本身就是一个装饰器)。您需要做的就是更改包装器声明:
@functools.wraps(f)
def wrapper(cls, _x):
return f(cls, _x) + _value
给定以下示例:
class A:
def f(self, x):
return 2*x
我想写另一个方法,它使用上面的 f
但添加一个常量,即
class A:
def f(self, x):
return 2*x
def g(self, x):
return self.f(x) + 10
这是一种方式。然而,这闻起来很像装修!执行此操作的正确 pythonic 方法是什么?
你可以在class外写一个简单的函数:
def add_val(f):
def wrapper(cls, _x):
return f(cls, _x) + 10
return wrapper
class A:
@add_val
def f(self, x):
return 2*x
print(A().f(20))
输出:
50
编辑:您可以在 Python3 中使用 functools.wraps
和 classmethod
。包装函数 f
将 return x*2
并且装饰器 g
会将 10
添加到传递给它的函数的 returned 结果。但是,为了能够保存 f
的原始功能,您可以利用 __wrapped__
属性:
import functools
def g(f):
@functools.wraps(f)
def wrapper(cls, _x):
return f(cls, _x)+10
return wrapper
class A:
@classmethod
@g
def f(cls, x):
return x*2
f_1 = functools.partial(A.f.__wrapped__, A)
print(A.f(4))
print(f_1(4))
输出:
18
8
@Ajax1234 的扩展答案,您可以尝试:
- 参数化你的装饰器,
- 显式调用你的装饰器(没有 @
)。
def add_val(_value):
def decorator(f):
def wrapper(cls, _x):
return f(cls, _x) + _value
return wrapper
return decorator
class A:
def f(self, x):
return 2*x
g = add_val(10)(f)
[编辑]
您还可以使用 functools.wraps()
改进装饰器(它本身就是一个装饰器)。您需要做的就是更改包装器声明:
@functools.wraps(f)
def wrapper(cls, _x):
return f(cls, _x) + _value