Online Book Reader

Home Category

Learning Python - Mark Lutz [530]

By Root 1892 0
this nested-function version works because Python creates a bound method object and thus passes the subject class instance to the self argument only when a method attribute references a simple function; when it references an instance of a callable class instead, the callable class’s instance is passed to self to give the callable class access to its own state information. We’ll see how this subtle difference can matter in more realistic examples later in this chapter.

Also note that nested functions are perhaps the most straightforward way to support decoration of both functions and methods, but not necessarily the only way. The prior chapter’s descriptors, for example, receive both the descriptor and subject class instance when called. Though more complex, later in this chapter we’ll see how this tool can be leveraged in this context as well.

Class Decorators

Function decorators proved so useful that the model was extended to allow class decoration in Python 2.6 and 3.0. Class decorators are strongly related to function decorators; in fact, they use the same syntax and very similar coding patterns. Rather than wrapping individual functions or methods, though, class decorators are a way to manage classes, or wrap up instance construction calls with extra logic that manages or augments instances created from a class.

Usage

Syntactically, class decorators appear just before class statements (just as function decorators appear just before function definitions). In symbolic terms, assuming that decorator is a one-argument function that returns a callable, the class decorator syntax:

@decorator # Decorate class

class C:

...

x = C(99) # Make an instance

is equivalent to the following—the class is automatically passed to the decorator function, and the decorator’s result is assigned back to the class name:

class C:

...

C = decorator(C) # Rebind class name to decorator result

x = C(99) # Essentially calls decorator(C)(99)

The net effect is that calling the class name later to create an instance winds up triggering the callable returned by the decorator, instead of calling the original class itself.

Implementation

New class decorators are coded using many of the same techniques used for function decorators. Because a class decorator is also a callable that returns a callable, most combinations of functions and classes suffice.

However it’s coded, the decorator’s result is what runs when an instance is later created. For example, to simply manage a class just after it is created, return the original class itself:

def decorator(C):

# Process class C

return C

@decorator

class C: ... # C = decorator(C)

To instead insert a wrapper layer that intercepts later instance creation calls, return a different callable object:

def decorator(C):

# Save or use class C

# Return a different callable: nested def, class with __call__, etc.

@decorator

class C: ... # C = decorator(C)

The callable returned by such a class decorator typically creates and returns a new instance of the original class, augmented in some way to manage its interface. For example, the following inserts an object that intercepts undefined attributes of a class instance:

def decorator(cls): # On @ decoration

class Wrapper:

def __init__(self, *args): # On instance creation

self.wrapped = cls(*args)

def __getattr__(self, name): # On attribute fetch

return getattr(self.wrapped, name)

return Wrapper

@decorator

class C: # C = decorator(C)

def __init__(self, x, y): # Run by Wrapper.__init__

self.attr = 'spam'

x = C(6, 7) # Really calls Wrapper(6, 7)

print(x.attr) # Runs Wrapper.__getattr__, prints "spam"

In this example, the decorator rebinds the class name to another class, which retains the original class in an enclosing scope and creates and embeds an instance of the original class when it’s called. When an attribute is later fetched from the instance, it is intercepted by the wrapper’s __getattr__ and delegated to the embedded instance of the original class. Moreover, each decorated class creates

Return Main Page Previous Page Next Page

®Online Book Reader