Professional Python. Luke Sneeringer

Читать онлайн книгу.

Professional Python - Luke Sneeringer


Скачать книгу
the terms of use and click Agree.

      3. Complete the required information to join, as well as any optional information you wish to provide, and click Submit.

      4. You will receive an e-mail with information describing how to verify your account and complete the joining process.

      Note

      You can read messages in the forums without joining P2P. However, in order to post your own messages, you must join.

      Once you join, you can post new messages and respond to messages other users post. You can read messages at any time on the web. If you would like to have new messages from a particular forum e-mailed to you, click the Subscribe to this Forum icon by the forum name in the forum listing.

      For more information about how to use the Wrox P2P, be sure to read the P2P FAQs for answers to questions about how the forum software works, as well as many common questions specific to P2P and Wrox books. To read the FAQs, click the FAQ link on any P2P page.

      Part I

      Functions

      Chapter 1

      Decorators

      A decorator is a tool for wrapping code around functions or classes. Decorators then explicitly apply that wrapper to functions or classes to cause them to “opt in” to the decorator's functionality. Decorators are extremely useful for addressing common prerequisite cases before a function runs (for example, ensuring authentication), or ensuring cleanup after a function runs (for example, output sanitization or exception handling). They are also useful for taking action on the decorated function or class itself. For example, a decorator might register a function with a signaling system or a URI registry in web applications.

      This chapter provides an overview of what decorators are and how they interact with Python functions and classes. It enumerates certain decorators that appear in the Python standard library. Finally, it offers instruction in writing decorators and attaching them to functions and classes.

      Understanding Decorators

      At its core, a decorator is a callable that accepts a callable and returns a callable. A decorator is simply a function (or other callable, such as an object with a __call__ method) that accepts the decorated function as its positional argument. The decorator takes some action using that argument, and then either returns the original argument or some other callable (presumably that interacts with it in some way).

      Because functions are first-class objects in Python, they can be passed to another function just as any other object can be. A decorator is just a function that expects another function, and does something with it.

      This sounds more confusing than it actually is. Consider the following very simple decorator. It does nothing except append a line to the decorated callable's docstring.

      Now, consider the following trivial function:

      The function's docstring is the string specified in the first line. It is what you will see if you run help on that function in the Python shell. Here is the decorator applied to the add function:

      Here is what you get if you run help:

      What has happened here is that the decorator made the modification to the function's __doc__ attribute, and then returned the original function object.

      Decorator Syntax

      Most times that developers use decorators to decorate a function, they are only interested in the final, decorated function. Keeping a reference to the undecorated function is ultimately superfluous.

      Because of this (and also for purposes of clarity), it is undesirable to define a function, assign it to a particular name, and then immediately reassign the decorated function to the same name.

      Therefore, Python 2.5 introduced a special syntax for decorators. Decorators are applied by prepending an @ character to the name of the decorator and adding the line (without the implied decorator's method signature) immediately above the decorated function's declaration.

      Following is the preferred way to apply a decorated_by decorator to the add method:

      Note again that no method signature is being provided to @decorated_by. The decorator is assumed to take a single, positional argument, which is the method being decorated. (You will see a method signature in some cases, but with other provided arguments. This is discussed later in this chapter.)

      This syntax allows the decorator to be applied where the function is declared, which makes it easier to read the code and immediately realize that the decorator is in play. Readability counts.

Order of Decorator Application

      When is a decorator applied? When the @ syntax is being used, decorators are applied immediately after the decorated callable is created. Therefore, the two examples shown of how to apply decorated_by to add are exactly equivalent. First, the add function is created, and then, immediately after that, it is wrapped with decorated_by.

      One important thing to note about this is that it is possible to use multiple decorators on a single callable (just as it is possible to wrap function calls multiple times).

      However, note that if you use multiple decorators using the @ syntax, they are applied in order, from bottom to top. This may be counterintuitive at first, but it makes sense given what the Python interpreter is actually doing.

      Consider the following function with two decorators applied:

      The first thing that occurs is that the add function is created by the interpreter. Then, the decorated_by decorator is applied. This decorator returns a callable (as all decorators do), which is then sent to also_decorated_by, which does the same; the latter result is assigned to add.

      Remember that the application of decorated_by is syntactically equivalent to the following:

      The previous two-decorator example is syntactically equivalent to the following:

      In both cases, the also_decorated_by decorator comes first as a human reads the code. However, the decorators are applied bottom to top for the same reason that the functions are resolved from innermost to outermost. The same principles are at work.

      In the case of a traditional function call, the interpreter must first resolve the inner function call in order to have the appropriate object or value to send to the outer call.

      With a decorator, first the add function is created normally.

      Then, the @decorated_by decorator is called, being sent the add function as its decorated method.

      The @decorated_by function returns its own callable (in this case, a modified version of add). That value is what is then sent to @also_decorated_by in the final step.

      When applying decorators, it is important for you to remember that they are applied bottom to top. Many times, order does


Скачать книгу