thorwhalen / umpyre

Materials for python coaching
MIT License
1 stars 0 forks source link

Repair a class decorator #20

Open thorwhalen opened 3 years ago

thorwhalen commented 3 years ago

class Enumerate:
    """Decorator a function so it enumerates the number of calls.
    Or in general, returns (cursor, func(x)) instead of just func(x), where the start and step of the cursor can
    be defined (default is start=0 and step=1)

    >>> def foo(x):
    ...    return x * 2
    >>> new_foo = Enumerate(foo)
    >>> new_foo('ha')
    (0, 'haha')
    >>> new_foo('ho')
    (1, 'hoho')
    >>> enum_foo_with_step = Enumerate(foo, start=3, step=7)
    >>> enum_foo_with_step('z')
    (3, 'zz')
    >>> enum_foo_with_step(11)
    (10, 22)
    """

    def __init__(self, func, start=0, step=1):
        self.func = func
        self.cursor = start
        self.step = step

    def __call__(self, *args, **kwargs):
        current_cursor = self.cursor
        out = self.func(*args, **kwargs)
        self.cursor += self.step
        return current_cursor, out

def with_cursor(func, start=0, step=1):
    """Decorator a function so it enumerates the number of calls.
    Or in general, returns (cursor, func(x)) instead of just func(x), where the start and step of the cursor can
    be defined (default is start=0 and step=1)

    >>> def foo(x):
    ...    return x * 2
    >>> new_foo = with_cursor(foo)
    >>> new_foo('ha')
    (0, 'haha')
    >>> new_foo('ho')
    (1, 'hoho')
    >>> enum_foo_with_step = with_cursor(foo, start=3, step=7)
    >>> enum_foo_with_step('z')
    (3, 'zz')
    >>> enum_foo_with_step(11)
    (10, 22)
    """
    def _func(*args, **kwargs):
        current_cursor = _func.cursor
        out = func(*args, **kwargs)
        _func.cursor += step
        return current_cursor, out

    _func.cursor = start
    return _func
from lined import Line
def foo(x):
    return x * 2

new_foo = Line(with_cursor(foo))
new_foo(3)  # gives me (0, 6) (correct!)

new_foo = Line(Enumerate(foo))
new_foo(3)  # gives me 6  (Not correct)

# yet
new_foo = Enumerate(foo)
new_foo(3)  # gives me (0, 6) (correct!)