Decorator question

Mark Summerfield list at qtrac.plus.com
Thu Jan 27 05:06:53 EST 2011


On Jan 27, 2:42 am, "Thomas L. Shinnick" <tshin... at io.com> wrote:
> At 08:17 PM 1/26/2011, Chris wrote:
>
> >I have a class (A, for instance) that possesses a boolean (A.b, for
> >instance) that is liable to change over an instance's lifetime.
>
> >Many of the methods of this class (A.foo, for instance) should not
> >execute as long as this boolean is false, but should instead raise an
> >exception.
>
> >Can I use a decorator to implement this functionality?  More exactly,
> >could I define a function called 'checker' that accomplishes this:
>
> Mark Summerfield's book "Programming in Python 3" has an example
> something like this (p.357) called 'positive_result'.   I hesitate to
> quote the entire thing, so I'll quote only the inner 'half' of the decorator:
>          def wrapper(*args, **kwargs):
>              result = function(*args, **kwargs)
>              assert result >= 0, function.__name__ + "() result isn't >= 0"
>              return result
>
> I would guess you would have to count on the first item in the
> methods' args to be self, and use that to test whether your attribute
> is false/true?
>
> Mark?
>
> >def checker(f):
> >     ...
>
> >class A():
>
> >     b = True
>
> >     @checker
> >     def foo(self,...):
> >         print 'in foo'
>
> >a = A()
> >a.foo()
> >a.b = False
> >a.foo()
>
> >would result in:
>
> >'in foo'
> >Exception: ...
>
> >This exact solution isn't necessary, just something that doesn't
> >require me to have the clunky:
>
> >def foo(self,...):
> >     if self.b:
> >         ...
> >     else: raise Exception('b attribute must be true before executing
> >this method')
>
> >in every method.
>
> >Thanks,
>
> >Chris

Here's a simple example that I think does what you're after:

##########################################

#!/usr/bin/env python3

import functools

def execute_if_valid(function):
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        if not args[0].valid:
            raise Exception("invalid instance")
        return function(*args, **kwargs)
    return wrapper

class A:
    valid = True

    def foo(self):
        print("called foo() on a valid or invalid instance")

    @execute_if_valid
    def bar(self):
        print("called bar() on a valid instance")

a = A()
a.foo()
a.bar()
a.valid = False
a.foo()
a.bar()

##########################################

Here's its output:

##########################################
called foo() on a valid or invalid instance
called bar() on a valid instance
called foo() on a valid or invalid instance
Traceback (most recent call last):
  File "./test.py", line 32, in <module>
    a.bar()
  File "./test.py", line 10, in wrapper
    raise Exception("invalid instance")
Exception: invalid instance
##########################################



More information about the Python-list mailing list