Overriding properties - Javaesque property rant

Kay Schluehr kay.schluehr at gmx.net
Sun Dec 12 10:36:00 CET 2004


> There are several ways to fix it. The simplest would be to create a
new
> property object in CC's definition:
>
> class CC(C):
>      def set_value(self, val):
>          if val < 0:
>              self.__val = 1
>          else:
>              self.__val = val
>      value = property(C.get_value, set_value)

It won't fix because __val is defined as a class variable in C, but as
an instance variable in CC. The set_value method creates a new __val. A
typical Python pitfall. C.get_value would still return _C__val.

> But an easier, more flexible method would be to use a metaclass which

> automatically adds properties for specially-named methods. One
example
> of such a metaclass is autoprop from Guido van Rossum's descrintro
> essay; see <URL:http://www.python.org/2.2.3/descrintro.html>.

Yes, but i dislike it either. This powerfull metaclass approach
obscures the property creation right in the place. And it supports the
tendency to create fat frameworks. A few weeks ago i talked to someone
who avoided propertys completely because they seemed to Javaesque to
him. I first agreed and understood his ranting about this awkward
get_bla, set_blubb stuff. Then I rembebered that the property()
function is just a descriptor-creator and one can easily wrap around it
for simplification.

So i defined defprop()

def defprop(name, default = None, modify=None, check=None, types=[]):

name  = "__"+name
def get(obj):
if not hasattr(obj,name):
setattr(obj,name, default)
return getattr(obj,name)

def set(obj,value):
if types:
if not True in [isinstance(value,t) for t in types]:
raise TypeError, "Can't assign %s to property
%s."%(value,name[2:])
if check:
if not check(value):
raise TypeError, "Can't assign %s to property
%s."%(value,name[2:])
if modify:
setattr(obj,name,modify(value))
else:
setattr(obj,name,value)

return property(get,set,None)


I left out to define delete. It was for demonstration purposes only.
Now define Your own classes:

class X(object):
a = defprop("a")
b = defprop("b",types=(tuple,list))
c = defprop("c",check = lambda x:hasattr(x,"__len__"))
d = defprop("d",default=0)

class XX(X):
def set_d(val):
if val<0:
return 1
return val

d = defprop("d",default=0,modify=set_d)  # overwrite d

It would be nice also to refuse the redundant naming a = defprop("a")
and write
a = defprop() instead. But it's actually not possible at the moment (
or only with deep introspection ).

Session on:

>>> x = X()
>>> x.d
0
>>> xx = XX()
>>> xx.d
0
>>> xx.d = -1
>>> xx.d
1

Ciao
     Kay




More information about the Python-list mailing list