Re: [Tutor] Difference between decorator and inheritance

2019-08-02 Thread Cameron Simpson

On 02Aug2019 11:26, bob gailer  wrote:

And now for something completely different...
Decorators are not required to return a function!
I use them to create a dictionary that maps function names to the 
corresponding function object.


That is an interesting idea! But I want to counter it, briefly.

This is very useful when associating actions with user-entered 
commands. Example:


def collect(func=None, d={}):
    if not func: return d
    d[func.__name__] = func

@collect
def add(a,b):
    return a+b

# adds item to dictionary d (key = 'add', value = func)
# repeat for other user-command functions
# finally:
cmd_dict = collect() # returns the dictionary
cmd = input('enter a command>')
func = cmd_dict.get(cmd)


I think you're conflating 2 things: having the decorator have a side 
effect outside the bare "do stuff around the call of an inner function", 
and returning a callable.


The feature of your remark is the side effect, which is useful. Not 
returning a callable is orthognal, and a misfeature.


Let me show you why:

   Python 3.7.4 (default, Jul 11 2019, 01:07:48)
   [Clang 8.0.0 (clang-800.0.42.1)] on darwin
   Type "help", "copyright", "credits" or "license" for more information.
   >>> d={}
   >>> def collect(f): d[f.__name__]=f
   ...
   >>> def g(x): print(x*2)
   ...
   >>> @collect
   ... def h(x): print(x*3)
   ...
   >>> g(8)
   16
   >>> h(8)
   Traceback (most recent call last):
 File "", line 1, in 
   TypeError: 'NoneType' object is not callable

The return value of the decorator is bound to the function name in the 
current scope,typically the current module for a normal function or the 
enclosing class for a method.


Your decorator returns None (I'm ignoring the d={} funkiness for now).  
Therefore a side effect of using the decorator is that every function 
"foo" you use with this decorator defines the name "foo" in the current 
scope as None.


As you can see in the example above, that makes the h() function not 
usable on its own. (And litters the namespace with a useless "h" name 
whose value is None.)


Had my version of your decorator looked like this:

   def collect(f):
   d[f.__name__] = f
   return f

then h() would have remained independently useful, at no cost to the 
functionality of your decorator.


So I'm arguing that while you _can_ return None from a decorator (which 
is what is actually happening in your "not returning" phrasing), it 
remains _useful_ and _easy_ to return the decorated function itself 
unchanged.


I've concerns about your d={} trick too, but we can discuss those in 
another subthread if you like.


I'm hoping to convince you that your otherwise nifty @collect decorator 
could do with returning the function unchanged after doing its work.


Finally, there is another important reason to return the function (or 
another callable): nesting decorators. Look at this piece of code from a 
project I'm working on:


   @classmethod
   @auto_session
   @require(lambda console: isinstance(console, Console))
   @require(lambda top_node: isinstance(top_node, DirTreeNode))
   @require(lambda top_node: not hasattr(top_node, 'can_uuid'))
   def from_fstree(cls, console, top_node, *, session):

This is a method, but otherwise the situation is no different. Each of 
these decorators does a little task and returns a callable, ready for 
further decoration by outer decorators. So every one of them returns a 
suitable callable.


If your @collect decorator returned the function, it too could be 
happily placed in such a nesting of decorators and everyone is happy.  
Because it does not, it does not play well with others, because an outer 
decorator would not have a callable to work with; it would get the None 
that your @collect returns.


This is the other argument for always returning a callable: to 
interoperate with other decorators, or of course anything else which 
works with a callable.


Cheers,
Cameron Simpson 
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Difference between decorator and inheritance

2019-08-02 Thread bob gailer

And now for something completely different...

Decorators are not required to return a function!

I use them to create a dictionary that maps function names to the 
corresponding function object.


This is very useful when associating actions with user-entered commands. 
Example:


def collect(func=None, d={}):
    if not func: return d
    d[func.__name__] = func

@collect
def add(a,b):
    return a+b

# adds item to dictionary d (key = 'add', value = func)
# repeat for other user-command functions
# finally:
cmd_dict = collect() # returns the dictionary
cmd = input('enter a command>')
func = cmd_dict.get(cmd)

--
Bob Gailer

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Difference between decorator and inheritance

2019-08-02 Thread Mats Wichmann
On 7/31/19 11:57 AM, Gursimran Maken wrote:
> Hi,
> 
> Anyone could please let me know the difference between decorators and
> inheritance in python.
> 
> Both are required to add additional functionality to a method then why are
> we having 2 separate things in python for doing same kind of work.

I started to write something here several times and never felt like I
got it right.  Let me try once more without fussing too much.

Python's decorators feel like a "local" thing - I have some code, and I
want to make some change to it.  Most often this comes up in predefined
scenarios - I enable one of my functions to be line-profiled by
decorating with @profile.  I turn an attribute into a getter by using
@property. I decorate to time a function. I decorate to add caching
(memoizing) capability (@functools.lru_cache).

If doesn't _have_ to be local; if I wanted to wrap a function that is
not in "my" code (e.g. from Python standard library, or some module that
I've obtained from the internet) I can, although the convenience form
using @decorator doesn't really apply here since I don't want to modify
"foreign" code; I have to use the underlying form of writing a function
that generates and returns a function which augments the original
function (that sounds so messy when you try to write it in English!).

Inheritance is a more systematic building of relationships between
classes - I can accomplish some of that with decorators, but not all.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Difference between decorator and inheritance

2019-08-01 Thread Alan Gauld via Tutor
On 31/07/2019 18:57, Gursimran Maken wrote:

> Anyone could please let me know the difference between decorators and
> inheritance in python.
> 
> Both are required to add additional functionality to a method then why are
> we having 2 separate things in python for doing same kind of work.

Inheritance and decorators can both achieve similar results in that
they provide a mechanism to alter the effect of a method, but they
work very differently. In particular, decorators can be used outside
of a class, on a normal function. They also work across multiple
different classes whereas works within a single heirarchy to create
a subtype structure (but see Mixins below).

Also, inheritance is used for much more than modifying methods.
You can add new methods and attributes and it also provides
conceptual structure to your classes as well as being a tool for
software reuse (probably its least useful, and most abused,
function). Inheritance in other OOP languages is used for
many other things too, especially as the mechanism that
enables polymorphism, but that is less significant in Python.

Where there is considerable overlap is in the use of mixin
classes. Mixins are a form of inheritance which allow
modification of methods in a way quite similar (from a
users perspective) to decorators. The underlying mechanisms
are different and decorators are more elegant, but the end
result is similar.

I'm not sure how much technical detail you wanted, so I'll
leave it thee, if you want to dig into the inner mechanisms
then ask for more details.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Difference between decorator and inheritance

2019-08-01 Thread Gursimran Maken
Hi,

Anyone could please let me know the difference between decorators and
inheritance in python.

Both are required to add additional functionality to a method then why are
we having 2 separate things in python for doing same kind of work.

Thank you,
Gursimran
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor