Python property decorators and set functions
I have some questions regarding the following code:
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()
- Why is a function needed
- Why can't I just
and then use
as a decorator directly?
When I do this, I get the error: x takes no arguments, one of them (presumably "i"). I know python has an option
, however I am forced to use 2.4 regularly so this is not an option for me. Even then
, it still seems less elegant than defining just one block.
Is there a way to define it all in one block with
source to share
You cannot use
as a decorator directly for the code you posted as it is not intended to be used in this way and it will not work.
If used as a decorator,
converts the function to a getter; if used as a function, you can pass to receiver, setter, deleter and doc.
It returns all locales, so you will have a dictionary with
that will lead to the removal
because it was passed too many arguments.
Personally, I like the style
since I have no extra function names in the class namespace.
If you need to use 2.4 regularly, just roll your own (or steal the latest from 2.6 like me;):
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
source to share
You can do it all in one block: without using
, defining and instantiating a class with methods
. See Implementing Descriptors for more details :
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()
is a shortcut for writing the above, and a method
in your example class is a shortcut for writing functions separately and passing them to
; instead, you write a function that defines the functions and then returns them where they are passed to
The reason you can't use
is because decorators decorate a single object. So you need a container, like a class, and so you can just write the handle directly at this point.
source to share