python - 属性装饰器的扩展行为
问题描述
我想扩展内置@property
装饰器的行为。所需的用法如下面的代码所示:
class A:
def __init__(self):
self.xy = 42
@my_property(some_arg="some_value")
def x(self):
return self.xy
print(A().x) # should print 42
首先,装饰器应该保留属性行为,以便()
在x
. 接下来,我希望能够访问程序员传递给我的装饰器的参数。
我从这个开始:
class my_property(property):
def __init__(self, fn):
super().__init__(fn)
TypeError: __init__() got an unexpected keyword argument 'some_arg'
添加后**kwargs
:
class my_property(property):
def __init__(self, fn, **kwargs):
super().__init__(fn)
TypeError: __init__() missing 1 required positional argument: 'fn'
好的,让我们*args
改为:
class my_property(property):
def __init__(self, *args, **kwargs):
super().__init__(*args)
TypeError: 'my_property' object is not callable
让我们让它可调用:
class my_property(property):
def __init__(self, *args, **kwargs):
super().__init__(*args)
def __call__(self, *args, **kwargs):
pass
No errors, but prints None instead of 42
现在我迷路了。我什至还没有设法访问 `some_arg="some_value" 并且属性行为似乎已经消失了。出了什么问题以及如何解决?
解决方案
目前尚不清楚您打算如何使用some_arg
,但是要将参数传递给装饰器,您需要有“两层”装饰器
@my_decorator(arg)
def foo():
return
在引擎盖下,这转化为my_decorator(arg)(foo)
(即my_decorator(arg)
必须返回另一个用 调用的装饰器foo
)。在这种情况下,内部装饰器应该是您自定义的属性实现
def my_property(some_arg):
class inner(object):
def __init__(self, func):
print(some_arg) # do something with some_arg
self.func = func
def __get__(self, obj, type_=None):
return self.func(obj)
return inner
现在你可以像这样使用它:
class MyClass:
def __init__(self, x):
self.x = x
@my_property('test!')
def foo(self):
return self.x
obj = MyClass(42) # > test!
obj.foo # > 42
在此处阅读有关描述符的更多信息