我想创建一个装饰器,允许我引用装饰对象并从中抓取另一个装饰器,就像在属性上使用setter / deleter一样:
@property
def x(self):
return self._x
@x.setter
def x(self, y):
self._x = y
具体来说,我希望它与属性基本相同,但是模拟序列而不是单个值。这是我的第一次拍摄,但它似乎不起作用:
def listprop(indices):
def dec(func):
class c(object):
def __init__(self, l):
self.l = l
def __getitem__(self, i):
if not i in self.l:
raise Exception("Invalid item: " + i)
return func(i)
@staticmethod
def setter(func):
def set(self, i, val):
if not i in self.l:
raise Exception("Invalid item: " + i)
func(i, val)
c.__setitem__ = set
return c(indices)
return dec
# ...
class P:
@listprop(range(3))
def prop(self, i):
return get_prop(i)
@prop.setter
def prop(self, i, val):
set_prop(i, val)
我很确定c.__setitem__ = set
是错误的,但我无法弄清楚如何在那时获得对实例的引用。想法?
Alex Martelli的解决方案适用于2.6,但有关它的一些内容在2.4和2.5上失败(我更喜欢它也适用于这些旧版本,尽管它并非绝对必要):
2.4:
>>> p = P()
>>> p.prop
>>> p.prop[0]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsubscriptable object
2.5:
>>> p = P()
>>> p.prop
>>> p.prop[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is unsubscriptable
2.6:
>>> p = P()
>>> p.prop
<__main__.c object at 0x017F5730>
>>> p.prop[0]
0
答案 0 :(得分:3)
我修复了许多小细节,以下版本似乎可以按您的要求运行:
def listprop(indices):
def dec(func):
class c(object):
def __init__(self, l, obj=None):
self.l = l
self.obj = obj
def __get__(self, obj, cls=None):
return c(self.l, obj)
def __getitem__(self, i):
if not i in self.l:
raise Exception("Invalid item: " + i)
return func(self.obj, i)
def setter(self, sfunc):
def doset(self, i, val):
if not i in self.l:
raise Exception("Invalid item: " + i)
sfunc(self.obj, i, val)
c.__setitem__ = doset
return self
result = c(indices)
return result
return dec
# ...
class P:
@staticmethod
def get_prop(i): return i*100
@staticmethod
def set_prop(i, val): print 'set %s to %s' % (i, val)
@listprop(range(3))
def prop(self, i):
return self.get_prop(i)
@prop.setter
def prop(self, i, val):
self.set_prop(i, val)
如您所见,分配给c.__setitem__
不是问题 - 还有其他问题,例如c缺少__get__
(因此它不是描述符,请参阅this guiide)并且setter返回None(所以p.prop最终为None)。