Re: [Tutor] Difference between decorator and inheritance
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
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
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
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
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