RFC: CmpTrue

John Hunter jdhunter at nitace.bsd.uchicago.edu
Thu Oct 31 11:42:33 EST 2002


After reading The Python Cookbook and being inspired by all the
examples where you can avoid the look before you leap paradigm with
exceptions, the Null design pattern and so on, I found myself wanting
to avoid the look-before-you-leap/no-good-default-at-init problem
discussed in the doc string below.


class CmpTrue:
    """
    Return true on any comparison.  This is useful when you want to
    set a default variable at initialization that will be overridden
    on first comparison, as in

    minVal = None
    for seq in allSeqs:
      minSeq = min(seq)
      if minVal is None:
        minVal = minSeq
        break
      if minSeq < minVal: minVal = minSeq

    This song and dance can be simplified in CmpTrue to
    minVal = CmpTrue()
    for seq in allSeqs:
      minSeq = min(seq)
      if minSeq < minVal: minVal = minSeq

    With the arithmetic functions defined to return a CmpTrue object,
    you can use the CmpTrue object in arithmetic computations

    lastTime = CmpTrue()
    
    def somefunc():
        global lastTime
        """This function will ignore repeated calls if the intercall
        interval is less than 1 second.  (inspired when pygtk
        repeatedly called my expose_event function on window resize)"""
        tnow = time.time()
        if tnow - lastTime > 1.0: 
            print 'OK'
            lastTime = tnow
        else: print 'Go Away, Monster'
    
    for i in range(10):
        somefunc()
        time.sleep(.3)

    Use with caution!
    
    """
    __returnTrue = ['__lt__', '__le__', '__eq__', '__ne__',
                    '__gt__', '__ge__', '__cmp__', '__rcmp__']



    __returnSelf = ['__add__', '__sub__', '__mul__', '__div__', '__mod__',
                    '__divmod__', '__pow__', '__lshift__', '__rshift__',
                    '__rsub__', '__rmul__', '__rdiv__', '__rmod__',
                    '__rdivmod__', '__rpow__', '__rlshift__', '__rrshift__']


    def __init__(self):
        for func in self.__returnTrue:
            self.__dict__[func] = self.__return_true

        for func in self.__returnSelf:
            self.__dict__[func] = self.__return_self

    def __return_self(self, arg=None):
        return self

    def __return_true(self, arg=None):
        return 1

    def __str__(self):
        return "It's true, really"

c = CmpTrue()

print 2*c-2
print 2*c-2 > 1


So the general problem I am trying to solve is when you have a numeric
variable where it is difficult to come up with an acceptable default
value at initialization, such as when you want to keep a running
minimum.  For a while, I used

  minVal = inf

which  can be used in code with

  if minSeq < minVal: minVal = minSeq

but this requires that inf is defined.  Using 1e300 at initialization
will get the job for most practical applications, but not all and
could represent a bug waiting to happen.

These are the kinds of default value/look before you leap problems
CmpTrue tries to solve.

Comments?  Perhaps the reduction of all arithmetic operations to self
if a gotcha waiting to happen, and is a bit heady handed...

Thanks,
John Hunter



More information about the Python-list mailing list