【问题标题】:A better python property decorator一个更好的python属性装饰器
【发布时间】:2011-02-06 07:49:35
【问题描述】:

我继承了一些 python 代码,其中包含一个相当神秘的装饰器。这个装饰器在整个项目的类中设置属性。问题是我已经将调试问题追溯到这个装饰器。似乎它“fubars”了我尝试过的所有调试器,并试图用 psyco 加速代码破坏一切。 (似乎 psyco 和这个装饰器玩得不好)。我认为最好改变它。

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 是否可以实现相同的装饰器。如果不是,我将进行一些重大的重写。

【问题讨论】:

    标签: python debugging properties decorator


    【解决方案1】:

    同样的事情?不,如果没有像 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 及更高版本中执行此操作的更惯用方式如下:

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

    【讨论】:

    • 我完全赞成用惯用的 python 方式做事,但最后一个例子似乎比我继承的“voodoo”装饰器可读性差。也许我只需要习惯它。 (惯用的方式,也就是)
    【解决方案2】:

    可能是可能的;似乎这种对settrace 的滥用被用来在装饰函数返回之前捕获装饰函数,以窃取它的局部变量......

    不幸的是,我目前能想到的主要方法是破解字节码 :-(.

    但是,您可以将其替换为需要每个如此装饰的函数调用另一个特殊函数而不是简单地返回的函数,或者您可以将其修改为调用 sys.gettrace 而不是丢弃任何可能处于活动状态的跟踪函数,并且之后恢复相同的跟踪功能。

    【讨论】:

    • 这就是我害怕的:)
    猜你喜欢
    • 2012-07-15
    • 2022-11-09
    • 2018-07-06
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 2017-03-18
    • 2013-03-17
    相关资源
    最近更新 更多