Welcome, guest | Sign In | My Account | Store | Cart

This recipe builds on two previously posted recipes for a null or dummy object by modifying a few methods (e.g. as in SQL, Null == Null is Null, not True), supporting most (all?) special methods (e.g. int(Null)) and providing correct pickling/unpickling.

Python, 66 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
__all__ = ['Null']

class NullType(object):
    '''An SQL-like Null object: allows most (if not all) operations on it to succeed.

    >>> repr(Null)
    '(Null)'
    >>> Null(3,x=3)
    (Null)
    >>> [Null==Null, Null!=None, Null<Null, Null>=3]
    [(Null), (Null), (Null), (Null)]
    >>> [Null[3], Null.foo]
    [(Null), (Null)]
    >>> Null[4] = 3
    >>> del Null['bar']
    >>> 2.5*Null + 3
    (Null)
    >>> [4 not in Null, 'all' in Null]
    [True, False]
    >>> list(Null)
    []
    >>> bool(Null)
    False
    >>> len(Null)
    0
    >>> [int(Null), long(Null), float(Null), complex(Null)]
    [0, 0, 0.0, 0j]
    >>> [oct(Null), hex(Null)]
    ['(Null)', '(Null)']
    >>> type(Null)() is Null
    True
    >>> from pickle import dumps, loads
    >>> loads(dumps(Null)) is Null
    True
    '''
    __singleton = None
    def __new__(cls, *args, **kwds):
        assert __name__ == '__main__', __name__
        if cls.__singleton is None:
            cls.__singleton = super(NullType,cls).__new__(cls)
        return cls.__singleton
    def __len__(self): return 0
    def __iter__(self): return; yield
    def __nonzero__ (self): return False
    def __contains__(self, item): return False
    def __repr__(self): return '(Null)'
    def __reduce__(self): return (type(self), ())
    __oct__ = __hex__ = __repr__
    __int__ = __long__ = __len__
    def __float__(self): return 0.0
    def __call__(self, *args, **kwds): return self
    __getitem__ = __getattr__ = __setitem__ = __setattr__ = __delitem__ = \
        __delattr__ = __eq__ = __ne__ = __gt__ = __ge__ = __lt__ = __le__ = \
        __neg__ = __pos__ = __abs__ = __invert__ = __add__ = __sub__ = \
        __mul__ = __div__ = __truediv__ = __floordiv__ = __mod__ = \
        __divmod__ = __pow__ = __lshift__ = __rshift__ =  __and__ = __or__ = \
        __xor__ = __radd__ = __rsub__ = __rmul__ = __rdiv__ = __rtruediv__ = \
        __rfloordiv__ = __rmod__ = __rdivmod__ = __rpow__ = __rlshift__ = \
        __rrshift__ = __rand__ = __ror__ = __rxor__ = __call__


Null = NullType()

if __name__ == '__main__':
    from doctest import testmod
    testmod()

1 comment

Aaron Gallagher 13 years ago  # | flag

Line 38 makes no sense to me. Why would you check if __name__ was __main__?

Also, there's not really any reason to use name mangling for the 'singleton' attribute. '_singleton' works just fine.