Marcus Goldfish wrote:
I'd like advice/opinions on when it is appropriate to do

Just an opinion...
attribute/property validation in python.  I'm coming from a C#/Java
background, where of course tons of "wasted" code is devoted to
property validation.  Here is a toy example illustrating my question:

#   Example: mixing instance attributes with properties.  Is it pythonic to
#   validate property data in setters?  Since tens and ones are never
#   validated, the class can be "broken" by setting these directly
class SillyDecimal(object):
   """A silly class to represent an integer from 0 - 99."""
   def __init__(self, arg=17):
       if isinstance(arg, tuple):
           self.tens = arg[0]
           self.ones = arg[1]
       else:
           self.number = arg

   def getNumber(self):
       return self.tens*10 + self.ones
   def setNumber(self, value):
       if value < 0 or value > 99:
           raise ArgumentException("Must in [0, 99]")
       self.tens = value // 10
       self.ones = value % 10
   number = property(getNumber, setNumber, None, "Complete number, [0-99]")

It is conventional to indicate 'private' attributes with the _ prefix.
By this standard, you have three 'public' interfaces: number, get/setNumber and ones/tens, which is confusing and error-prone. Moreover, if you are going to validate number, it might make more sense to put all the validation logic into the setter vs. splitting some into __init__. So your class could look like:


class SillyDecimal1(object):
    """A silly class to represent an integer from 0 - 99."""
    def __init__(self, value = 17):
        self.number = value
    def _getNumber(self):
       return self._tens*10 + self._ones
    def _setNumber(self, value):
        if isinstance(value, tuple):
            value  = value[0] * 10 + value[1]
        if value in range(100):
            self._tens = value /10
            self._ones = value % 10
        else:
            raise ValueError, "Number out of range(100)"
    number = property(_getNumber, _setNumber, None, "Complete number, [0-99]"

There is nothing to stop a user from setting _tens and _ones directly, but their names indicate that this should not be done.

As for whether it is appropriate to validate the value at all, I think that depends on your larger design.

Note that one of the main purposes of properties is retrofitting bare attributes with getters/setters. So, an initial version of your class might be:

class SillyDecimal0(object):
    """A silly class to represent an integer from 0 - 99."""
    def __init__(self, value = 17):
        self.number = value

Later you can add the getter/setter/property logic if it turns out to be necessary, without changing the interface (except for the addition of a couple of 'private' attributes and 'private' methods, which well-behaved callers should not touch anyway.


Michael

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to