Checking length of each argument - seems like I'm fighting Python

Mike Meyer mwm at mired.org
Sun Dec 4 01:12:54 EST 2005


"Brendan" <spam4bsimons at yahoo.ca> writes:
> There must be an easy way to do this:

Not necessarily.

> For classes that contain very simple data tables, I like to do
> something like this:
>
> class Things(Object):
>     def __init__(self, x, y, z):
>         #assert that x, y, and z have the same length
>
> But I can't figure out a _simple_ way to check the arguments have the
> same length, since len(scalar) throws an exception.  The only ways
> around this I've found so far are

You've gotten a number of suggestions about how to type check
things. To me, the need to type check things indicates that your API
has problems. In particular, when you're doing it on arguments, it's
indicative of trying to do the C++ thing of dispatching based on the
types of the arguments. Given duck typing, this is nearly impossible
to do correctly.

> Is there a simpler way to check that either all arguments are scalars,
> or all are lists of the same length?  Is this a poor way to structure
> things?  Your advice is appreciated

I'd say your better off providing two different interfaces to
Thing. The hard-core OO way would look like:

class Thing(object):
      def use_lists(self, x, y, z):
          assert len(x) == len(y) == len(z)
          self.x, self.y, self.z = x, y, z
      def use_scalars(self, x, y, z):
          self.x, self.y, self.z = x, y, z

This allows things that type-checking can't do. For instance, the user
can treat strings as either a scalar or sequence, their choice. If you
do the type-checking, you'll have to choose one case and stick with
it.

Also, I suspect that you can actually change do_scalars to something like
      self.x, self.y, self.z = [x], [y], [z]
and then the rest of your code will get simpler because it only has to
deal with lists.

You might also make use optional arguments, and check that you get passed
a proper subset:

class Thing(object):
      def __init__(self, x = None, y = None, z = None, scalars = None):
          if scalars:
             if x is not None or y is not None or z is not None:
                raise ValueError, "If present, scalars must be the only argument."
             self.x, self.y, self.z = scalars
          elif not (x is not None and y is not None and z is not None):
             raise ValueError, "You must specify all of x, y and z"
          else:
             assert len(x) == len(y) == len(z)
             self.x, self.y, self.z = x, y, z

etc.

        <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list