Any, All predicates (and vector operations for free)
Christos TZOTZIOY Georgiou
DLNXPEGFQVEB at spammotel.com
Sun Feb 16 07:59:00 EST 2003
Hello, people
I have created a class that allows ANY and ALL predicates on iterables;
it was easy to also allow vector operations (eg add something to every
item on the list).
However, to define class methods 'en masse', the only way I finally
found to do it was using the exec statement; 'setattr(klass,
attribute_name, result)' didn't do its magic.
Can you suggest a better method? Look at the 'exec' statement in the
class All definition to see what I mean. Example usage is at the end of
the code.
BTW, would you consider these as a worthy candidate for inclusion in the
standard library? Do you often need to check that some condition
applies to all items of a sequence? If yes, please suggest any changes
to the class name, module name or even to the source. I am using these
two classes quite often, and I think they add to the legibility of my
algorithms.
Thanks in advance for any replies.
*** predicates.py ***
import __builtin__, operator
class All(object):
"""Array operations on every element of its argument."""
__slots__ = ("_iterable",)
def __init__(self, iterable):
self._iterable = iterable
def _new_result(self):
"""Initialise a new list of results (internal)."""
return [None]*len(self._iterable)
def __nonzero__(self):
"""Return nonzero if all results are nonzero."""
return len(filter(None, self._iterable)) == len(self._iterable)
def _multi_(method, operate=False):
try:
default_operation = getattr(operator, method)
except AttributeError:
default_operation = None
def operate(self, *values):
"""Call a method on every item of self._iterable."""
result = self._new_result()
for ix, item in enumerate(self._iterable):
if default_operation:
result[ix] = default_operation(item, *values)
else:
result[ix] = getattr(item, method)(*values)
return self.__class__(result)
return operate
for method in \
"add,sub,mul,div,truediv,mod,floordiv,abs,neg,pos,pow,repeat,"\
"lshift,rshift," \
"cmp,eq,le,lt,gt,ge,ne," \
"call," \
"inv,invert,not,and,or,xor," \
"getitem,getslice," \
"contains,concat".split(","):
exec "%s = _multi_('%s')" % ( ("__%s__" % method,)*2 )
del _multi_, method
def result(self):
"""Return a list of results."""
return self._iterable
def __iter__(self):
"""Iterate through self._iterable ."""
return iter(self._iterable)
def __getattr__(self, attribute):
"""Return a list of every item's attribute."""
result = self._new_result()
for ix, item in enumerate(self._iterable):
result[ix] = getattr(item, attribute)
return self.__class__(result)
class Any(All):
__slots__ = ("_iterable",)
def __nonzero__(self):
"""Return nonzero if any result is non zero."""
return bool(filter(None, self._iterable))
if __name__ == "__main__":
li = [0, 2, 4, 6, 8]
ls = ["hello", "hell", "help"]
print "Integer list:", li
print "String list:", ls
# call a method on all items
if All(ls).startswith("hel"):
print "All strings start with 'hel'"
else:
print "[ERROR] Some strings do not start with 'hel'!!!"
# do math operations on all items
print "Add 5 to integer list:", (All(li)+5).result()
if "el" in All(ls):
print "All strings contain 'el'."
else:
print "[ERROR] Some strings do not contain 'el'!!!"
if All(li)%2 == 0:
print "All integers are even."
else:
print "[ERROR] Some integers are not even!!!"
if "elp" in Any(ls):
print "Some strings contain 'elp'."
else:
print "[ERROR] No strings contain 'elp'!!!"
--
TZOTZIOY, I speak England very best,
Real email address: 'dHpvdEBzaWwtdGVjLmdy\n'.decode('base64')
More information about the Python-list
mailing list