Python和set函数中的属性装饰器

提问

我对以下代码有一些疑问:

  1 class Test(object):
  2     def __init__(self):
  3         print "Object instance created."
  4         self._x = raw_input("Initial value of x = ")
  5         print "Initial value of x set."
  6 
  7     def Property(func):
  8         return property(**func())
  9 
 10     @Property
 11     def x():
 12         def fget(self):
 13             print 'Getting x'
 14             return self._x
 15         def fset(self, val):
 16             print 'Setting x'
 17             self._x = val
 18         def fdel(self):
 19             print 'Deleting x'
 20             del self._x
 21         doc = "A test case"
 22         return locals()

>为什么需要Property()函数?
>为什么我不能只返回locals()然后直接使用@property作为装饰器?

当我这样做时,我得到一个错误,说x不接受任何参数,给定了一个参数(大概是“ self”).我知道python具有@ x.setter选项,但是我被迫定期使用2.4,所以它对我来说不是一个选项.即使这样,@ x.setter仍然看起来似乎比在一个块中定义它还要优雅.

有没有一种方法可以使用@property在一个块中全部定义?

最佳答案

您不能直接将属性用作发布代码的修饰器,因为它不是设计用于这种方式的,因此无法正常工作.

如果用作装饰器,则property会将函数转换为getter;如果用作函数,则可以传入getter,setter,deleter和doc.

locals()返回所有本地人,因此您将拥有一个包含fget,fset,fdel,doc,Property和__init__的字典-导致property爆炸,因为它传递了太多参数.

就我个人而言,我喜欢@ x.setter和@ x.deleter样式,因为在类名空间中我不会以不必要的函数名结尾.

如果您必须定期使用2.4,只需自己滚动(或像我一样从2.6中窃取最新版本;):

    class property(object):
        "2.6 properties for 2.5-"    
        def __init__(self, fget=None, fset=None, fdel=None, doc=None):
            self.fget = fget
            self.fset = fset
            self.fdel = fdel
            self.__doc__ = doc or fget.__doc__
        def __call__(self, func):
            self.fget = func
            if not self.__doc__:
                self.__doc__ = fget.__doc__
        def __get__(self, obj, objtype=None):
            if obj is None:
                return self         
            if self.fget is None:
                raise AttributeError("unreadable attribute")
            return self.fget(obj)
        def __set__(self, obj, value):
            if self.fset is None:
                raise AttributeError("can't set attribute")
            self.fset(obj, value)
        def __delete__(self, obj):
            if self.fdel is None:
                raise AttributeError("can't delete attribute")
            self.fdel(obj)
        def setter(self, func):
            self.fset = func
            return self
        def deleter(self, func):
            self.fdel = func
            return self
评论