装饰类python,Python中的装饰器类

  • Post author:
  • Post category:python


I want to construct classes for use as decorators with the following principles intact:

It should be possible to stack multiple such class decorators on top off 1 function.

The resulting function name pointer should be indistinguishable from the same function without a decorator, save maybe for just which type/class it is.

Ordering off the decorators should not be relevant unless actually mandated by the decorators. Ie. independent decorators could be applied in any order.

This is for a Django project, and the specific case I am working on now the method needs 2 decorators, and to appear as a normal python function:

@AccessCheck

@AutoTemplate

def view(request, item_id) {}

@AutoTemplate changes the function so that instead of returning a HttpResponse, it just returns a dictionary for use in the context. A RequestContext is used, and the template name is inferred from the method name and module.

@AccessCheck adds additional checks on the user based on the item_id.

I am guessing it’s just to get the constructor right and copy the appropriate attributes, but which attributes are these?

The following decorator won’t work as I describe:

class NullDecl (object):

def __init__ (self, func):

self.func = func

def __call__ (self, * args):

return self.func (*args)

As demonstrated by the following code:

@NullDecl

@NullDecl

def decorated():

pass

def pure():

pass

# results in set([‘func_closure’, ‘func_dict’, ‘__get__’, ‘func_name’,

# ‘func_defaults’, ‘__name__’, ‘func_code’, ‘func_doc’, ‘func_globals’])

print set(dir(pure)) – set(dir(decorated));

Additionally, try and add “print func.name” in the NullDecl constructor, and it will work for the first decorator, but not the second – as name will be missing.

Refined eduffy’s answer a bit, and it seems to work pretty well:

class NullDecl (object):

def __init__ (self, func):

self.func = func

for n in set(dir(func)) – set(dir(self)):

setattr(self, n, getattr(func, n))

def __call__ (self, * args):

return self.func (*args)

def __repr__(self):

return self.func

解决方案

A do-nothing decorator class would look like this:

class NullDecl (object):

def __init__ (self, func):

self.func = func

for name in set(dir(func)) – set(dir(self)):

setattr(self, name, getattr(func, name))

def __call__ (self, *args):

return self.func (*args)

And then you can apply it normally:

@NullDecl

def myFunc (x,y,z):

return (x+y)/z