Python中的属性修饰器和设置函数

时间:2012-03-08 22:43:30

标签: python properties get set decorator

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

  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()
  1. 为什么需要Property()功能?
  2. 为什么我不能return locals()然后直接使用@property作为装饰者?
  3. 当我这样做时,我得到一个错误,说x没有参数,一个给出(大概是'自我')。我知道python有@x.setter选项,但我不得不经常使用2.4,所以对我来说这不是一个选择。即便如此,@x.setter似乎仍然不如在一个区块中定义所有内容。

    有没有办法使用@property在一个块中定义所有内容?

2 个答案:

答案 0 :(得分:2)

您不能将property直接用作您所发布的代码的装饰器,因为它不是设计为以这种方式使用,而且无法使用。

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

locals()会返回所有本地人,因此您将拥有一个包含fgetfsetfdeldoc的词典,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

答案 1 :(得分:2)

可以在一个块中完成所有操作:不是通过使用@property来定义和实例化具有__get__()__set__()和{{的类1}}方法。有关详细信息,请参阅Implementing Descriptors

__delete__()

class Test(object): def __init__(self): print "Object instance created." self._x = raw_input("Initial value of x = ") print "Initial value of x set." class x(object): def __get__(self, instance, owner): print 'Getting x' return instance._x def __set__(self, instance, value): print 'Setting x' instance._x = value def __delete__(self, instance): print 'Deleting x' del instance._x __doc__ = "A test case" x = x() 是编写上述内容的快捷方式,示例类中的property()方法是必须单独编写函数并将其传递给Property()的快捷方式。相反,你编写一个定义函数的函数,然后返回它们,并将它们传递给property()

您无法使用property()的原因是装饰器装饰单个对象。所以你需要一个容器,比如一个类,所以你也可以直接在那一点写一个描述符。