2010-04-09 20 views
3

我已經繼承了一些包含相當神祕的修飾器的python代碼。這個裝飾器在整個項目中設置類的屬性。問題是,我已經將我的調試問題追溯到這個裝飾器。看來它是「fubar」我試過的所有調試器,並試圖加速與psyco代碼打破everthing。 (似乎psyco和這個裝飾器不玩很好)。我認爲最好改變它。一個更好的python屬性修飾器

def Property(function): 
    """Allow readable properties""" 
    keys = 'fget', 'fset', 'fdel' 
    func_locals = {'doc':function.__doc__} 
    def probeFunc(frame, event, arg): 
     if event == 'return': 
      locals = frame.f_locals 
      func_locals.update(dict((k,locals.get(k)) for k in keys)) 
      sys.settrace(None) 
     return probeFunc 
    sys.settrace(probeFunc) 
    function() 
    return property(**func_locals) 

使用像這樣:

class A(object): 
    @Property 
    def prop(): 
     def fget(self): 
      return self.__prop 
     def fset(self, value): 
      self.__prop = value 
    ... ect 

的錯誤,我得到說的問題都是因爲sys.settrace。 (也許這是濫用settrace?)

我的問題:是否可以實現相同的裝飾沒有 sys.settrace。如果不是,我會進行一些重寫。

回答

8

同樣的事情?不。你不能做那個裝飾器d沒有像sys.settrace這樣的魔法。 (它在技術上不一定是sys.settrace,但是使用別的東西 - 比如字節碼重寫 - 不會有什麼改進)。例如,您可以通過做更簡單的事情來做到這一點:例如:

def Property(f): 
    fget, fset, fdel = f() 
    fdoc = f.__doc__ 
    return property(fget, fset, fdel, fdoc) 

class Foo(object): 
    @Property 
    def myprop(): 
     "Property docstring" 
     def fget(self): 
      return 'fget' 
     def fset(self, x): 
      pass 
     def fdel(self): 
      pass 
     return fget, fset, fdel 

在Python 2.6和更高版本,您可以使用一個稍微不同的裝飾,雖然:

def Property(cls): 
    fget = cls.__dict__.get('fget') 
    fset = cls.__dict__.get('fset') 
    fdel = cls.__dict__.get('fdel') 
    fdoc = cls.__doc__ 
    return property(fget, fset, fdel, fdoc) 

而且你會使用它,像這樣:

class Foo(object): 
    @Property 
    class myprop(object): 
     "Property docstring" 
     def fget(self): 
      return 'fget' 
     def fset(self, x): 
      pass 
     def fdel(self): 
      pass 

然而,在Python這樣做的更地道的方式2.6和lat呃是像這樣:

class Foo(object): 
    @property 
    def myprop(self): 
     "Property docstring" 
     return 'fget' 
    @myprop.setter 
    def myprop(self, x): 
      pass 
    @myprop.deleter 
    def myprop(self): 
      pass 
+2

我所有的處事習慣蟒蛇的方式,但最後的例子似乎比我繼承了「巫毒」裝飾的可讀性。也許我只需要習慣它。 (慣用的方式,那就是) – jtm 2010-04-09 20:44:12

2

可能是可能的;看起來,這個settrace的濫用正在被用來在它返回之前捕獲裝飾函數,目的是爲了竊取它的局部變量...

不幸的是,目前我能想到的主要方法涉及黑客字節碼:-(。

然而,你可以用一個需要每個如此修飾的函數來調用另一個特殊函數而不是簡單地返回,或者你可以修改它來調用sys.gettrace而不是拋出任何可能的trace函數激活,然後恢復相同的跟蹤功能。

+0

這是我所擔心的:) – jtm 2010-04-09 20:42:29