Last active
July 14, 2022 09:53
-
-
Save kernc/9484240 to your computer and use it in GitHub Desktop.
Null object pattern (Python)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This module provides the Null class for the null object design pattern. | |
""" | |
from collections import MutableMapping, MutableSequence | |
class _MetaNull(type): pass | |
class Null(type): | |
"""Null object design pattern. | |
This class traps and ignores everything. Instances of it always and | |
reliably do nothing, or return 0, '', False, or other logical, | |
contextually-appropriate emptiness or negation. | |
>>> Null()(1, kwarg=2)()[3]['4'] is Null | |
True | |
>>> Null.method().attr is Null | |
True | |
>>> Null * 1 / 2 + 3 == Null | |
<Null> | |
>>> bool(Null), str(Null), repr(Null), int(Null), len(Null) | |
(False, '', '<Null>', 0, 0) | |
>>> [i for i in Null] | |
[] | |
Roughly, the goal with Null objects is to provide an 'intelligent' | |
replacement for the often used primitive data type None in Python | |
or Null (or Null pointers) in other languages. These are used for | |
many purposes including the important case where one member of some | |
group of otherwise similar elements is special for whatever reason. | |
Most often this results in conditional statements to distinguish | |
between ordinary elements and the primitive Null value. | |
Among the advantages of using Null objects are the following: | |
* Superfluous conditional statements can be avoided | |
by providing a first class object alternative for | |
the primitive value None. | |
* Code readability is improved. | |
* Null objects can act as a placeholder for objects | |
with behaviour that is not yet implemented. | |
* Null objects can be replaced for any other class. | |
* Null objects are very predictable at what they do. | |
To cope with the disadvantage of creating large numbers of passive | |
objects that do nothing but occupy memory space Null objects are | |
often combined with the Singleton pattern. | |
For more information use any internet search engine and look for | |
combinations of these words: Null, object, design and pattern. | |
Dinu C. Gherman, | |
August 2001 | |
""" | |
__metaclass__ = _MetaNull | |
__hash__ = type.__hash__ | |
__slots__ = () | |
def __next__(_): raise StopIteration | |
next = __next__ # Python 2 compatibility | |
__dir__ = lambda _: [] | |
__str__ = lambda _: '' | |
__repr__ = lambda _: '<Null>' | |
__bytes__ = lambda _: b'' | |
__int__ = \ | |
__len__ = \ | |
__index__ = \ | |
__round__ = \ | |
__complex__ = lambda *_: 0 | |
__float__ = lambda *_: 0. | |
__eq__ = \ | |
__ge__ = \ | |
__gt__ = \ | |
__le__ = \ | |
__lt__ = \ | |
__ne__ = \ | |
__or__ = \ | |
__and__ = \ | |
__del__ = \ | |
__get__ = \ | |
__set__ = \ | |
__abs__ = \ | |
__add__ = \ | |
__mod__ = \ | |
__mul__ = \ | |
__new__ = \ | |
__neg__ = \ | |
__pos__ = \ | |
__pow__ = \ | |
__ror__ = \ | |
__sub__ = \ | |
__xor__ = \ | |
__call__ = \ | |
__exit__ = \ | |
__init__ = \ | |
__iter__ = \ | |
__radd__ = \ | |
__rand__ = \ | |
__rmod__ = \ | |
__rmul__ = \ | |
__rpow__ = \ | |
__rsub__ = \ | |
__rxor__ = \ | |
__enter__ = \ | |
__delete__ = \ | |
__divmod__ = \ | |
__invert__ = \ | |
__lshift__ = \ | |
__rshift__ = \ | |
__delattr__ = \ | |
__delitem__ = \ | |
__getattr__ = \ | |
__getitem__ = \ | |
__rdivmod__ = \ | |
__rlshift__ = \ | |
__rrshift__ = \ | |
__setattr__ = \ | |
__setitem__ = \ | |
__truediv__ = \ | |
__floordiv__ = \ | |
__rtruediv__ = \ | |
__rfloordiv__ = \ | |
__getattribute__ = lambda self, *_, **__: self | |
Null.__class__ = Null | |
class nulldict(dict): | |
def __missing__(self, key): | |
return Null | |
class nulllist(list): | |
def __getitem__(self, i): | |
return list.__getitem__(self, i) if i < len(self) else Null | |
class nulltuple(tuple): | |
def __getitem__(self, i): | |
return tuple.__getitem__(self, i) if i < len(self) else Null | |
def nullify(obj): | |
if isinstance(obj, MutableMapping): | |
return nulldict(obj) | |
if isinstance(obj, tuple): | |
return nulltuple(obj) | |
if isinstance(obj, MutableSequence): | |
return nulllist(obj) | |
return obj or Null |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
L153, grammar mistakes.