Advice requested on class design

Walter Wefft walterwefft at googlemail.com
Wed Apr 28 15:34:40 CEST 2010


Alan Ristow wrote:
> 
> I would like to have three classes, ClassA, ClassB, and ClassC, that are 
> essentially the same, the only difference being that each class has a 
> different range of valid values for its properties. Thus, the obvious 
> solution is to create a base class, then subclass from that and include 
> the required error-checking during initialization and when property 
> values change. The base class might look something like this:
[...]
> 
> However, instead of rewriting my validation code in several different 
> places, I would prefer to write it one time and keep it in one place. I 
> can write a function or method that I call each time I need to do 
> validation, which is the approach I would take in most languages. 
> However, since I am basically writing several small variations on one 
> theme, it seems like in Python this might be an ideal application for 
> decorators and/or metaclasses.
> 
> So my question is, what is the most sensible way to write a set of 
> classes such as these in Python? I am not afraid to experiment with 
> decorators or metaclasses -- indeed, I would love to learn more about 
> them -- but in this particular project I do not want to use them just 
> for the sake of learning to use them. If there is a good reason to use 
> them, I am all for it, though.
> 
> All advice appreciated,
> 
> Thanks,
> 
> Alan
> 

There's probably a number of ways to do it, but Descriptors spring to mind:


class x_validator(object):

     def __get__(self, instance, cls):
         return instance._x

     def __set__(self, instance, val):
         if instance.is_valid_x(val):
             instance._x = val
         else:
             raise ValueError("'%s' is an invalid value for 'x'" % val)

class Base(object):

     _x = None
     x = x_validator()

     def __init__(self, x):
         self.x = x

class A(Base):

     def is_valid_x(self, val):
         return val < 10

class B(Base):

     def is_valid_x(self, val):
         return val > 0


a = A(2)

print(a.x)
print(a._x)

a.x = 12

b = B(-2)


(you might not want to define _x at the class-level).




More information about the Python-list mailing list