Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Python uses duck-typing, rather than static type checking. But many of the same concerns ultimately apply: does an object have the desired methods and attributes? Do those attributes have valid, in-range values?

Whether you're writing constraints in code, or writing test cases, or validating user input, or just debugging, inevitably somewhere you'll need to verify that an object is still in a proper state--that it still "looks like a duck" and "quacks like a duck."

In statically typed languages you can simply declare "int x", and anytime you create or mutate x, it will always be a valid int. It seems feasible to decorate a Python object to ensure that it is valid under certain constraints, and that every time that object is mutated it is still valid under those constraints. Ideally there would be a simple declarative syntax to express "hasattr length and length is non-negative" (not in those words. Not unlike Rails validators, but less human-language and more programming-language). You could think of this as ad-hoc interface/type system, or you could think of it as an ever-present object-level unit test.

Does such a library exist to declare and validate constraint/duck-checking on Python-objects? Is this an unreasonable tool to want? :)

(Thanks!)


Contrived example:

rectangle = {'length': 5, 'width': 10}

# We live in a fictional universe where multiplication is super expensive.  
# Therefore any time we multiply, we need to cache the results.

def area(rect):
    if 'area' in rect:
        return rect['area']
    rect['area'] = rect['length'] * rect['width']
    return rect['area']

print area(rectangle)
rectangle['length'] = 15
print area(rectangle) # compare expected vs. actual output!

# imagine the same thing with object attributes rather than dictionary keys.
share|improve this question
1  
hasattr length would be handled with duck typing (error if it's not there), while length >= 0 could be a condition on the setter side of a property. –  Izkata Mar 30 '12 at 21:32
1  
@Izkata. Right, exactly! It seems like there should be a library that can automatically declare and enforce those across a wide number of aspects of an object at once, and I am curious if that library exists. –  elliot42 Mar 30 '12 at 21:35
2  
You're a bit vague on what you want to do. When do you want the checks to occur? Checking what attributes exist doesn't really need a library since Python supports a lot of introspection already. Other validations could be done in various ways, such as attributes. As far as simple syntax, Python usual does such things in Python rather than inventing a syntax. –  psr Mar 30 '12 at 21:40
1  
The whole point of duck-typing is that you don't check those things explicitly - you do your stuff, and if it's not sufficently duck-like, it fails. –  delnan Mar 30 '12 at 21:41
    
@psr Checks should occur 1) Either when an object is created, or when you first add the validator to the object, 2) Any time the object is mutated, e.g. foo.bar = baz Yes, it's all doable manually, but there's no reason why should have to write the same boiler plate over every attribute of every object. –  elliot42 Mar 30 '12 at 21:56

2 Answers 2

up vote 3 down vote accepted

It sounds like you want class invariants. That link (a deferred PEP) is the first Google search result for "class invariants in Python". The second is a link to an existing library: PyDBC. I haven't used it before, but it appears to do what you're after.

import os
os.environ['PY_DBC'] = 'true'
import dbc

class Rect:
    __metaclass__ = dbc.DBC
    def __init__(self, length, width):
        self.length = length
        self.width = width
        self.area = length*width
    def __invar(self):
        if hasattr(self, "area"): # __invar gets called during __init__ too :(
            assert self.area == (self.length * self.width)

r = Rect(4, 5)
r.length = 123
share|improve this answer

Remember that duck typing is really just an (implicit) promise to implement certain methods, with the agreement that the call will fail at run time rather than at compile time. Because of that, a ducktyper would really just be an explicit promise - which isn't really that different from an interface.

I know that zope has an implementation of interfaces - http://wiki.zope.org/zope3/WhatAreInterfaces

Although I haven't used it personally

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.