"""
This file demonstrates using decorators that are object methods
to add state without resorting to global variables.
"""


class CallCounter:
    """A stateful function wrapper as a class"""
    def __init__(self):
        self.count = 0
    def decorator(self, f):
        def g(*args, **kargs):
            self.count += 1
            return f(*args, **kargs)
        return g
    def __str__(self):
        return 'CallCount:{}'.format(self.count)

cc = CallCounter()

@cc.decorator
def is_sorted(seq):
    seq = (x for x in seq) # convert to a generator
    
    try: last = seq.__next__() # first thing if there is one
    except StopIteration: return True # empty = sorted
    
    for val in seq:
        if val < last: return False
        last = val
    
    return True

print(cc)
print(is_sorted([]))
print(cc)
print(is_sorted([1,2,3]))
print(is_sorted([1,2,1]))
print(is_sorted([3,2,1]))
print(cc)