2009-06-23 234 views
1

我想創建一個裝飾,讓我重提裝飾對象,並從中攫取另一裝飾,您可以使用屬性的setter /缺失者以同樣的方式:裝飾物是裝飾物的屬性?

@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是錯誤的,但我無法弄清楚如何在那得到的實例的引用點。想法?

亞歷克斯·馬爾泰利的解決方案適用於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

爲什麼不簡單地將屬性值設置爲列表? – 2009-06-23 15:16:35

回答

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)。