total_ordering
and force_total_ordering
are class decorators for
Python 2.6 & Python 3.
They provides all the rich comparison methods on a class by defining any one of '__lt__', '__gt__', '__le__', '__ge__'.
total_ordering
fills in all unimplemented rich comparison methods, assuming
at least one is implemented. __lt__
is taken as the base comparison method
on which the others are built, but if that is not available it will be
constructed from the first one found.
force_total_ordering
does the same, but having taken a comparison method as
the base it fills in all the others - this overwrites additional comparison
methods that may be implemented, guaranteeing consistent comparison semantics.
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | # By Christian Muirhead, Menno Smits and Michael Foord 2008
# WTF license
# http://voidspace.org.uk/blog
"""
``total_ordering`` and ``force_total_ordering`` are class decorators for
Python 2.6 & Python 3.
They provides *all* the rich comparison methods on a class by defining *any*
one of '__lt__', '__gt__', '__le__', '__ge__'.
``total_ordering`` fills in all unimplemented rich comparison methods, assuming
at least one is implemented. ``__lt__`` is taken as the base comparison method
on which the others are built, but if that is not available it will be
constructed from the first one found.
``force_total_ordering`` does the same, but having taken a comparison method as
the base it fills in *all* the others - this overwrites additional comparison
methods that may be implemented, guaranteeing consistent comparison semantics.
::
from total_ordering import total_ordering
@total_ordering
class Something(object):
def __init__(self, value):
self.value = value
def __lt__(self, other):
return self.value < other.value
It also works with Python 2.5, but you need to do the wrapping yourself:
::
from total_ordering import total_ordering
class Something(object):
def __init__(self, value):
self.value = value
def __lt__(self, other):
return self.value < other.value
total_ordering(Something)
It would be easy to modify for it to work as a class decorator for Python
3.X and a metaclass for Python 2.X.
"""
import sys as _sys
if _sys.version_info[0] == 3:
def _has_method(cls, name):
for B in cls.__mro__:
if B is object:
continue
if name in B.__dict__:
return True
return False
else:
def _has_method(cls, name):
for B in cls.mro():
if B is object:
continue
if name in B.__dict__:
return True
return False
def _ordering(cls, overwrite):
def setter(name, value):
if overwrite or not _has_method(cls, name):
value.__name__ = name
setattr(cls, name, value)
comparison = None
if not _has_method(cls, '__lt__'):
for name in 'gt le ge'.split():
if not _has_method(cls, '__' + name + '__'):
continue
comparison = getattr(cls, '__' + name + '__')
if name.endswith('e'):
eq = lambda s, o: comparison(s, o) and comparison(o, s)
else:
eq = lambda s, o: not comparison(s, o) and not comparison(o, s)
ne = lambda s, o: not eq(s, o)
if name.startswith('l'):
setter('__lt__', lambda s, o: comparison(s, o) and ne(s, o))
else:
setter('__lt__', lambda s, o: comparison(o, s) and ne(s, o))
break
assert comparison is not None, 'must have at least one of ge, gt, le, lt'
setter('__ne__', lambda s, o: s < o or o < s)
setter('__eq__', lambda s, o: not s != o)
setter('__gt__', lambda s, o: o < s)
setter('__ge__', lambda s, o: not (s < o))
setter('__le__', lambda s, o: not (s > o))
return cls
def total_ordering(cls):
return _ordering(cls, False)
def force_total_ordering(cls):
return _ordering(cls, True)
def _test():
class Thing(object):
def __init__(self, val):
self.val = val
class Thing_lt(Thing):
def __lt__(self, other):
return self.val < other.val
class Thing_gt(Thing):
def __gt__(self, other):
return self.val > other.val
class Thing_ge(Thing):
def __ge__(self, other):
return self.val >= other.val
class Thing_le(Thing):
def __le__(self, other):
return self.val <= other.val
for cls in [Thing_lt, Thing_gt, Thing_le, Thing_ge]:
print (cls.__name__)
for ordering in (total_ordering, force_total_ordering):
cls = ordering(cls)
t1 = cls(1)
t2 = cls(2)
assert t1 < t2, 'lt'
assert t1 == t1, 'eq'
assert t1 != t2, 'ne'
assert t2 > t1, 'gt'
assert t2 >= t2, 'ge'
assert t1 <= t1, 'le'
print ('no errors')
if __name__ == '__main__':
_test()
|
i was wondering if this could apply, or if you can easily program such, to a simple protocol for determining whether or not a word within a current law is literally (=) constitutional according to the Unabridged English Dictionary of 1776 which was used by Benjamin Franklin [Library of Congress], who signed, both, the Declaration of Independence and the Constitution. A simple example might be: the word "bureau" does not appear within the Constitution, Declaration of Independence, or any of the American Indian treaties which were legalized upon the signing of the Constitution, thus, any laws pertaining to "bureaus" would be, for the purposes of this program, deemed technically (=) unconstitutional and, as such, would be automatically sorted into another "bin" for correction, further analysis, and/or expurgation of all information which does not fit precisely within the parameters of the full original definitions, punctuation included. please, advise. itequates@yahoo.com
See recipe 576685 for a simpler approach and faster comparison methods.