【发布时间】:2009-06-23 14:59:12
【问题描述】:
我想创建一个装饰器,它允许我引用被装饰的对象并从中获取另一个装饰器,就像在属性上使用 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
【问题讨论】:
-
为什么不简单地将属性值设置为列表?
-
@S.Lott:因为我不需要列表,所以我需要一个看起来像列表的对象,但实际上通过使用列表索引作为附加参数从其他地方获取它的值.事实上,我需要其中的几个,它们都做非常相似但略有不同的事情。