osdir.com

```No, I see this as teaching the skills involved to drive a car. Practicing a
turn, scanning gauges, and checking blind spots are all a part of driving.
When one is learning, it's easier to learn these in isolation so when the
problem must be solved in real time, you know what to do. This is no
different. You may never need to use a decorator ever in your development
career, but the tool is there in case the problem you have can be elegantly
solved using one.

-Jorge

On Tue, Oct 3, 2017 at 8:00 AM, bartc <bc at freeuk.com> wrote:

> On 03/10/2017 15:39, Ian Kelly wrote:
>
>> On Tue, Oct 3, 2017 at 4:41 AM, Steve D'Aprano
>> <steve+python at pearwood.info> wrote:
>>
>>> On Tue, 3 Oct 2017 06:51 am, Bill wrote:
>>>
>>> Can you inspire me with a good decorator problem (standard homework
>>>> exercise-level will be fine)?
>>>>
>>>
>>>
>>> Here is a nice even dozen problems for you. Please ask for clarification
>>> if any
>>> are unclear.
>>>
>>>
>>>
>>> (1) Write a decorator which simply prints a descriptive message and the
>>> name of
>>> the decorated function once, when the function is first decorated.
>>>
>>> E.g. if you write:
>>>
>>> @decorate
>>> def spam(x):
>>>      return x + 1  # for example
>>>
>>> print(spam(1))
>>> print(spam(2))
>>>
>>>
>>> Python should print:
>>>
>>> Decorating function spam.
>>> 2
>>> 3
>>>
>>>
>>> Note: "spam" must not be hard-coded, it must be taken from the function
>>> being
>>> decorated. (Hint: all functions have their name available as
>>> func.__name__.)
>>>
>>>
>>> (2) Modify the decorator from (1) so that calling the wrapped function
>>> also
>>> print a descriptive message such as "Calling function spam". The expected
>>> output will be:
>>>
>>> Decorating function spam.
>>> Calling function spam.
>>> 2
>>> Calling function spam.
>>> 3
>>>
>>>
>>> (3) Write a decorator that checks that the decorated function's first
>>> argument
>>> is a non-empty string, raising an appropriate exception if it is not,
>>> and lets
>>> through any other arguments unchanged.
>>>
>>>
>>> (4) Same as above, except the first argument is automatically stripped of
>>> leading and trailing whitespace and forced to uppercase.
>>>
>>>
>>> (5) Write a decorator which injects the argument 10 into the list of
>>> arguments
>>> received by the wrapped function. E.g. if you write:
>>>
>>> @inject
>>>      return a + b
>>>
>>> @inject
>>> def sub(a, b):
>>>      return a - b
>>>
>>>
>>> Python should print "15 5". (And *not* "15 -5".)
>>>
>>>
>>> (6) [ADVANCED] Modify the decorator in (5) so that it takes an argument
>>> telling
>>> it what value to inject into the list of arguments:
>>>
>>> @inject(99)
>>> def sub(a, b):
>>>      return a - b
>>>
>>> print(sub(5))
>>>
>>> will now print "94".
>>>
>>>
>>> (7) Write a decorator which checks the decorated function's two
>>> arguments are
>>> given smallest first, swapping them around if needed.
>>>
>>>
>>> (8) Write a decorator which prints the name of the wrapped function, its
>>> arguments, and the time, each time the wrapped function is called.
>>>
>>>
>>> (9) [ADVANCED] Modify the decorator from (8) to take an argument
>>> specifying the
>>> path to a file, and use the logging module to log the details to that
>>> file
>>>
>>>
>>> (10) Write a decorator which adds an "cache" attribute initialised to an
>>> empty
>>> dictionary to the decorated function.
>>>
>>>
>>> (11) Write a decorator which wraps a class (not function!), and adds a
>>> "help"
>>> method to the class which prints a message as shown below. For example:
>>>
>>> class Spam:
>>>      pass
>>>
>>> class Eggs:
>>>      pass
>>>
>>> x = Spam()
>>> x.help()
>>> y = Eggs()
>>> y.help()
>>>
>>> will print:
>>>
>>> See http://example.com/Spam
>>> See http://example.com/Eggs
>>>
>>> (Hint: classes also have a __name__ attribute.)
>>>
>>>
>>> (12) [ADVANCED] Write a decorator which wraps a class, and applies the
>>> decorator
>>> from (10) above to each non-dunder? method in the class. That is, after:
>>>
>>> class MyClass:
>>>      def foo(self):
>>>          pass
>>>      def bar(self):
>>>          pass
>>>
>>> print(MyClass.foo.cache, MyClass.bar.cache)
>>>
>>> should print "{} {}".
>>>
>>>
>>>
>>> trailing underscores: "Double UNDERscore" methods.
>>>
>>
> [Sorry can't see Steve's original post.]
>
> Does all this advanced stuff (which I don't understand and which doesn't
> look very appealing either; hopefully I will never come across such code)
> still count as programming?
>
> It seems to me the equivalent of an advanced driving course teaching you
> how to customise your car rather than involving any actual driving.
>
> --
> bartc
> --
> https://mail.python.org/mailman/listinfo/python-list
>

```