Python style: to check or not to check args and data members

Robert Kern robert.kern at
Fri Sep 1 01:56:26 CEST 2006

Joel Hedlund wrote:
> Hi!
> The question of type checking/enforcing has bothered me for a while, and 
> since this newsgroup has a wealth of competence subscribed to it, I 
> figured this would be a great way of learning from the experts. I feel 
> there's a tradeoff between clear, easily readdable and extensible code 
> on one side, and safe code providing early errors and useful tracebacks 
> on the other. I want both! How do you guys do it? What's the pythonic 
> way? Are there any docs that I should read? All pointers and opinions 
> are appreciated!

Short answer: Use Traits. Don't invent your own mini-Traits.

(Disclosure: I work for Enthought.)

Unfortunately, I think the standalone tarball on that page, uh, doesn't stand 
alone right now. We're cleaning up the interdependencies over the next two 
weeks. Right now, your best bet is to get the whole enthought package:

Talk to us on enthought-dev if you need any help.

Now back to Traits itself:

Traits does quite a bit more than "type-checking," and I think that is its 
least-useful feature that it provides for Python users. Types are very 
frequently exactly the wrong thing you want to check for. They allow inputs that 
you would like to be invalid and disallow inputs that would have worked just 
fine if you had relied on duck-typing. In general terms, Traits does 
value-checking; it's just that some of the traits definitions check values by 
validating their types.

You have to be careful with type-checking, because it can introduce fragility 
without enhancing safety. But sometimes you are working with other code that 
necessarily has type requirements (like extension code), and moving the 
requirements forward a bit helps build usable interfaces.

Your examples would look like this with Traits:

from enthought.traits.api import HasTraits, Int, method

class MyClass(HasTraits):
     """My example class.

     int_member = Int(0, desc="I am an integer")

     method(None, Int)
     def process_data(self, data):
          """Do some data processing.

          self.int_member += 1

a = MyClass(int_member=9)
a = MyClass(int_member='moo')
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "/Users/kern/svn/enthought-lib/enthought/traits/", line 
172, in error
     raise TraitError, ( object, name,, value )
enthought.traits.trait_errors.TraitError: The 'int_member' trait of a MyClass 
instance must be a value of type 'int', but a value of moo was specified.

# and similar errors for
# a.int_member = 'moo'
# a.process_data('moo')

The method() function predates 2.4 and has not yet been converted to a 
decorator. We don't actually use it much.

Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco

More information about the Python-list mailing list