我想扩展内置@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”,并且该属性的行为似乎已经消失了。有什么问题以及如何解决?
答案 0 :(得分:1)
目前尚不清楚您打算如何使用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
详细了解descriptors here