The Natural class implementation

Now we merely have to provide an implementation for our Natural class.

Create a file src/transient/natural.py under your Grok instance and give it the contents:

class Natural(object):
    """A natural number, here defined as an integer greater than zero."""

    def __init__(self, n):
        self.n = abs(int(n)) or 1

    def __str__(self):
        return '%d' % self.n

    def __repr__(self):
        return 'Natural(%d)' % self.n

    @property
    def previous(self):
        if self.n < 2:
            raise AttributeError('There is no natural number less than 1.')
        return Natural(self.n - 1)

    @property
    def next(self):
        return Natural(self.n + 1)

    @property
    def factors(self):
        if not hasattr(self, '_factors'):  # compute factors only once!
            n, i = self.n, 2
            self._factors = []
            while i <= n:
                while n % i == 0:          # while n is divisible by i
                    self._factors.append(Natural(i))
                    n /= i
                i += 1
        return self._factors

    @property
    def is_prime(self):
        return len(self.factors) < 2

    @property
    def is_composite(self):
        return len(self.factors) > 1

If you try running ./bin/test again after creating this file, you should find that the entire natural.txt docfile now runs correctly!

I hope that if you are new to Python, you are not too confused by the code above, which uses @property which may not have been covered in the Python tutorial. But I prefer to show you “real Python” like this, that reflects how people actually use the language, rather than artifically simple code that hides from you the best ways to use Python. Note that it is not necessary to understand natural.py to enjoy the rest of this tutorial! Everything we do from this point on will involve building a framework to use this object on the web; we will be doing no further development on the class itself. So all you actually need to understand is how a Natural behaves, which was entirely explained in the doctest.

Note that the Natural class knows nothing about Grok! This is an important feature of the whole Zope 3 framework, that bears frequent repeating: objects are supposed to be simple, and not have to know that they are being presented on the web. You should be able to grab objects created anywhere, from any old library of useful functions you happen to download, and suit them up to be displayed and manipulated with a browser. And the Natural class is exactly like that: it has no idea that we are about to build a framework around it that will soon be publishing it on the web.