|
|
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.