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