#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    10
    Rep Power
    0

    Co-routines/decorators


    Within a file called coroutines1.py, write a coroutines, capitalize that capitalizes and prints each word it is sent. Instantiate this coroutine, and test it with the phrase, "The quick brown fox jumped over the lazy old dog."

    Within a file called coroutines2.py, repeate the exercise described for generators2.py, but use a pipeline of coroutines. In effect, the "first" corroutine in the pipeline will strip punctuation and the last will print the word. You can read the words from the file however you'd like -- including by using the generator you wrote earlier

    Within a file called decorators.py, write two decorators, one, nonNegative which assumes an arbitrarily long list of integer arguments and throws an Exception if any is less than 0, and another, allCaps, which assumes an arbitrarily long list of string arguments, and capitalizes them. Then, write a simple function to test each, wrap it, and demonstrate that each decorator works.

    Im not too good with decorators/co-routines. can someone help explain this to me?
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,854
    Rep Power
    481
    Of your 4 paragraphs, the first and second tasks are similar and we answered a similar request within the last few days. Read the recent posts in this forum. As I recall it was solved except for the upper case generator, for which there are so many clues and templates that failure would be challenging.

    A decorator is similar to an adverb. An adverb modifies a verb. Let's write sufficient facts. The constraints will be so severe that the decorator will write itself. Python says
    • A decorator is a callable. Therefore it is either a function or a class with a __call__ method.
    • The argument to the decorator is an OriginalFunction.
    • The decorator returns a NewFunction.
    Your assignment requires of the NewFunction that it
    • accept an arbitrary number of arguments;
    • raises an exception if any of the arguments are not whole numbers;
    • because we're working with decorators implies that we'll call the OriginalFunction after verifying the arguments and return its result


    Let's name the decorator function whole_numbers, and let's have it raise WholeNumberException when it encounters bad data.

    Step 1: write a test. We'll decorate wholesum, the test function. Your program now looks like this
    Code:
    '''
        This file is named p.py
        With python being the name that invokes your python3 executable,
        run doctest using the command
          python -m doctest p.py
    
        >>> wholesum(*range(11))
        55
    '''
    We run doctest and sure enough, the test fails. Next implement wholesum. The incremental source is
    Code:
    '''
        This file is named p.py
        With python being the name that invokes your python3 executable,
        run doctest using the command
          python -m doctest p.py
    
        >>> wholesum(*range(11))
        55
    '''
    
    def wholesum(*args):
        return sum(args)
    Run the test. Test passes, it works. We plan to decorate wholesum to make it work according to its name. Insert more tests, run them, and they fail. These tests satisfy me as enough tests.
    Code:
    '''
        This file is named p.py
        With python being the name that invokes your python3 executable,
        run doctest using the command
          python -m doctest p.py
    
        >>> wholesum(*range(11))
        55
        >>> wholesum(-1, *range(11))
        Traceback (most recent call last):
            ...
        WholeNumberException: arguments are restricted to whole numbers.
        >>> wholesum('NOT A NUMBER')
        Traceback (most recent call last):
            ...
        WholeNumberException: arguments are restricted to whole numbers.
        >>> wholesum(1.0)
        Traceback (most recent call last):
            ...
        WholeNumberException: arguments are restricted to whole numbers.
    '''
    
    def wholesum(*args):
        return sum(args)
    Right. They fail. Let's finish the program.
    Code:
    '''
        This file is named p.py
        With python being the name that invokes your python3 executable,
        run doctest using the command
          python -m doctest p.py
    
        >>> wholesum(*range(11))
        55
        >>> wholesum(-1, *range(11))
        Traceback (most recent call last):
            ...
        p.WholeNumberException: arguments are restricted to whole numbers.
        >>> wholesum('NOT A NUMBER')
        Traceback (most recent call last):
            ...
        p.WholeNumberException: arguments are restricted to whole numbers.
        >>> wholesum(1.0)
        Traceback (most recent call last):
            ...
        p.WholeNumberException: arguments are restricted to whole numbers.
    '''
    
    class WholeNumberException(ValueError):
        '''
            We said we needed a WholeNumberException and this is IT!
        '''
        def __init__(self,*args,**kwargs):
            super().__init__('arguments are restricted to whole numbers.')
    
    def whole_numbers(OriginalFunction):
        '''
            This is the decorator.
            Our decorator is a callable named whole_numbers
            that takes a function argument.
        '''
        def NewFunction(*args): # the new function takes an arbitrary number of arguments
            # test each argument that it is integral and non-negative
            if not all(isinstance(a, int) and (-1 < a) for a in args):
                raise WholeNumberException()
            # Use the OriginalFunction and return its result.
            return OriginalFunction(*args)
        # and return a function, the NewFunction.
        return NewFunction
    
    # and USE the decorator
    @whole_numbers
    def wholesum(*args):
        return sum(args)
    This passes the test on my current system. My thoughts.
    • I did not expect to need to concatenate the module name p. to the Exception in the doctest.
    • The last chunk of code required to pass the final tests was too large a step. I tried about 5 versions before the test passed. For instance, I forgot to use the decorator. I forgot to return NewFunction. Had I sooner adhered to my premise that "the facts almost entirely pin down the decorator" the only two errors I'd have made would have been the in the whole number test logic and prepending the module name to the exception.
    • In production code I would define the wholesum test function within the doctest.
    • wholesum should have had a docstring. Anyway, it's supposed to return the sum of its arguments, and only if they are whole numbers. Retrofitting this post to pretend that a docstring was there from the start is both painful and dishonest.


    That's how I work, and that's a way to write a decorator. It's cleaner using a class, in my opinion. Now write the capitalization decorator or whatever.
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    10
    Rep Power
    0
    Hmm, I see what you are trying to say but i'm still a bit confused as to how to implement this for the nonNegative LISTS that could be placed in.. sorry about the trouble!
  6. #4
  7. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,854
    Rep Power
    481
    You got the message that as long as I'm solving your homework I figured I might as well also show you how to program? Test first is one way, a good enough way to get you employed.
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo