What is a wrapper? What is a Decorator?

Started by
11 comments, last by Tangletail 8 years, 8 months ago

I need the most basic, "for dummies" explanation of what a wrapper is. I posted this in "For Beginners" because I am sure someone will just starting out will have the same question.

So far my definition is:

A function that calls or returns another function

Wikipedia makes this so difficult and annoying to comprehend:

A wrapper function is a subroutine in a software library or a computer program whose main purpose is to call a second subroutine[1] or a system call with little or no additional computation.

Isn't a subroutine a function?

Wikipedia says:

In computer programming, a subroutine is a sequence of program instructions that perform a specific task, packaged as a unit.

Do I have this idea right:

Sometimes I don't like the name of a function included in a library, so I put that function in a function of my own, and pass stuff into it, or return stuff from it.

But then, what is a decorator?

I am using Python, but this paradigm shows up in several languages.

Edit:

Found another quote from (http://www.programiz.com/python-programming/decorator):

Basically, a decorator takes in a function, adds some functionality and returns it.

Edit: Found another explanation (http://thecodeship.com/patterns/guide-to-python-function-decorators/)

In other words, functions generating other functions
There is a neat shortcut for that, which is to mention the name of the decorating function before the function to be decorated. The name of the decorator should be perpended with an @ symbol.
The examples in this post are pretty simple relative to how much you can do with decorators. They can give so much power and elegance to your program. In general, decorators are ideal for extending the behavior of functions that we don't want to modify.

They call me the Tutorial Doctor.

Advertisement
In my view, a wrapper is literally a wrapper

def f(x, y, z): return original_f(x, y, z)

examples are call forwarders to internal objects, and proxies.


A decorator adds functionality, for example memoization, or access control, etc.

I once used a web frame-work, where a decorator was used to attach an url to the function (a page handler function thus).

A wrapper function or class is just a piece of code that envelopes existing code, while adding new functionality before (e.g. initialization) or after (e.g. clean up) the existing code. Example:


file* loadImageWrapper(string filename)
{
    if (!fileExists(filename))
         // Handle error

    result = loadImage(filename);   // Original function

    if (!result)
        // Handle error 
}

The wrapper could of course be more complex than that depending on the situation. It could also simply not have any new code added and just be used to set up a new name for the existing function.

AFAIK, decorators are the same thing as wrappers.

"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "

When you say that it is a piece of code that envelopes existing code, it sounds much like a function inside of a function. Whereas recursion is when a function calls itself, I am supposing a wrapper is the function that calls another function. Or perhaps even, it returns that same function (slightly modified even).

I am thinking of a programming analogy (code that is analogous to real life) that demonstrates wrappers and decorators.

They say decorators are syntactic sugar (easier on the eyes?) for wrappers. So a decorator is a "better way" to create a wrapper? Or is it a better way to apply a wrapper?

Is my idea still correct? Is it a function that calls or returns another function? From my research, it seems there is a broader definition.


def candy():
    return "candy"

def wrapper():
    return candy()

print(wrapper())

Yea? If so, how would this become a decorator? Decorate the wrapper with something? Or do we decorate the candy?

They call me the Tutorial Doctor.

Wrapper and decorator mean about the same it adds some specific functionality to an object/function without touching objects/function that are similar as the object you decorated. Usually you use this when you have a specific need to do something different but you don't need to rewrite a whole new class to do this action.

The wikipedia article about the decorator pattern has a good example of a window decorator for example that adds the ability to have a scrollbar next to a window without having to add the scrollbar functionality to the window class.

Decorators will usually have the same interface that the underlying class has but in the functions where it calls the functions of the class underneath it adds functionality that it has to do to the execution of that function.

The distinction between a wrapper and a decorator is more the pattern in how it is applied, you usually talk about decorators when talking about classes that wrap the functionality of other ones and add a specific functionality to the execution stack. Wrapper functions is more when you wrap call to a method of a global instance in a global function, wrappers are usually nothing more as function wrapped around another one, generally their scope is smaller.

But are used to implement plugable/extendable behavior to an existing class/function that might be black box.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

Syntactic sugar means it's not new functionality (ie you can make wrapper functions without using decorators), but it's simpler in use (less clutter, or more intuitive syntax).

A decorator in Python defines a function (the wrapper function). I seldomly use them, but iirc a decorator is a function that takes the original function as argument, and returns a new (the wrapper function) as result.


@deco 
def f(...):  
  # original function contents 
calls the 'deco' function, giving the orignal function contents reference. The return result (the wrapped f) is added to the current scope as 'f', so the other code can find it.

So @deco hides the need to rename the old function, and eliminates the need to make a new 'def f' with the wrapper and a call to the old functionality.

The above is not entirely true, you could also do @deco decoration after definition


def f(...): 
   ...  
f = deco(f) 
But your deco call is then at a different place than the 'f' definition.

Edit: code layout fixing
First, divide the code into interfaces (types, function argument lists and return values) and behavior (the fundamental process that the classes and functions are meant to perform).


Adapters keep the same behavior but modify the interface. This is done when you want one function/class to use another one, using an existing interface which the second function/class doesn't quite match. An adapter is written which converts the second function/class/etc's interface into one that the first function/class can use.

Decorators keep the same interface but modify behavior. This is done when you want to reuse most of some existing code, but tweak it slightly and allow your new code to be used anywhere the existing code can be used.


"Wrapper" is ambiguous and can mean either Adapter or Decorator. It's more common to mean Adapter, though.

Its just another layer of indirection, just like getters/setters, functions, etc... (well I guess everythings just functions, but gotta love them indirections)

Has same benefits as those, reduces redundant information, reduces impact of changes on other code, makes bugs harder to introduce, acts as a well defined interface to make code more readable...

o3o


Wrapper -

Added functionality can include mapping over error returns from the called function(s) into the specific error handling of the program/application.
--------------------------------------------[size="1"]Ratings are Opinion, not Fact
A wrapper is a thin layer of code written over another set of code to achieve essentially the same result through another interface.
The main component of my graphics engine is a wrapper around OpenGL, OpenGL ES, Direct3D 9, Direct3D 11, and Metal.
This means you use my wrapper’s interface, such as CGfx::Clear() or CGfx::Present(), and internally it will achieve the same end result whether you are in OpenGL or Direct3D, etc.


I won’t describe “decorators” because it is not a term I have ever used.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement