deferred decorator

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Bryan

    #1

    deferred decorator

    i was intrigued with a recently posted cookbook recipe which implements deferred
    results with decorators:



    the problem i see with this recipe is that the author only tested his code by
    printing the values which causes __getattr__ to be called with '__str__' and
    work correctly. but, if you were to remove the print statements and just do a v
    + v, __getattr__ won't get called as he expected and the join will never happen.
    i think by making __coerce__ as smart as __getattr__ this recipe would work.
    can someone validate that i'm correct in what i'm saying?

    i'm also curious if it's possible to write this recipe using the new class style
    for the Deffered class. it appears you can nolonger delegate all attributes
    including special methods to the contained object by using the __getattr__ or
    the new __getattribute_ _ methods. does anyone know how to port this recipe to
    the new class style?

    thanks,

    bryan
  • Nick Coghlan

    #2
    Re: deferred decorator

    Bryan wrote:[color=blue]
    > i'm also curious if it's possible to write this recipe using the new
    > class style for the Deffered class. it appears you can nolonger
    > delegate all attributes including special methods to the contained
    > object by using the __getattr__ or the new __getattribute_ _ methods.
    > does anyone know how to port this recipe to the new class style?[/color]

    Override __getattribute_ _. I don't know why you think it doesn't let you
    override all attribute accesses, as that's exactly what it is for.

    Cheers,
    Nick.

    --
    Nick Coghlan | ncoghlan@email. com | Brisbane, Australia
    ---------------------------------------------------------------

    Comment

    • Bryan

      #3
      Re: deferred decorator

      Nick Coghlan wrote:[color=blue]
      > Bryan wrote:
      >[color=green]
      >> i'm also curious if it's possible to write this recipe using the new
      >> class style for the Deffered class. it appears you can nolonger
      >> delegate all attributes including special methods to the contained
      >> object by using the __getattr__ or the new __getattribute_ _ methods.
      >> does anyone know how to port this recipe to the new class style?[/color]
      >
      >
      > Override __getattribute_ _. I don't know why you think it doesn't let you
      > override all attribute accesses, as that's exactly what it is for.
      >
      > Cheers,
      > Nick.
      >[/color]

      here's an example. __getattribute_ _ gets called for x but not for the special
      method __add__. and the __str__ method was found in the base class object which
      printed the memory location, but didn't call __getattribute_ _. so
      __getattribute_ _ cannot be used to capture special methods and delegate them to
      an encapsulated object. this is why i'm asking what the technique using new
      classes would be for this recipe.

      [color=blue][color=green][color=darkred]
      >>> class Foo(object):[/color][/color][/color]
      .... def __getattribute_ _(self, name):
      .... raise AttributeError( '__getattribute __ is called')
      ....[color=blue][color=green][color=darkred]
      >>> f = Foo()
      >>> f.x()[/color][/color][/color]
      Traceback (most recent call last):
      File "<interacti ve input>", line 1, in ?
      File "<interacti ve input>", line 3, in __getattribute_ _
      AttributeError: __getattribute_ _ is called[color=blue][color=green][color=darkred]
      >>> f + f[/color][/color][/color]
      Traceback (most recent call last):
      File "<interacti ve input>", line 1, in ?
      TypeError: unsupported operand type(s) for +: 'Foo' and 'Foo'[color=blue][color=green][color=darkred]
      >>> str(f)[/color][/color][/color]
      '<__main__.Foo object at 0x0118AD10>'


      Comment

      • Nick Coghlan

        #4
        Re: deferred decorator

        Bryan wrote:[color=blue]
        > Nick Coghlan wrote:
        >[color=green]
        >> Bryan wrote:
        >>[color=darkred]
        >>> i'm also curious if it's possible to write this recipe using the new
        >>> class style for the Deffered class. it appears you can nolonger
        >>> delegate all attributes including special methods to the contained
        >>> object by using the __getattr__ or the new __getattribute_ _ methods.
        >>> does anyone know how to port this recipe to the new class style?[/color]
        >>
        >>
        >>
        >> Override __getattribute_ _. I don't know why you think it doesn't let
        >> you override all attribute accesses, as that's exactly what it is for.
        >>
        >> Cheers,
        >> Nick.
        >>[/color]
        >
        > here's an example. __getattribute_ _ gets called for x but not for the
        > special method __add__. and the __str__ method was found in the base
        > class object which printed the memory location, but didn't call
        > __getattribute_ _. so __getattribute_ _ cannot be used to capture special
        > methods and delegate them to an encapsulated object. this is why i'm
        > asking what the technique using new classes would be for this recipe.[/color]

        Hmm, good point. I now have a vague idea why it happens that way, too
        (essentially, it appears the setting of the magic methods causes the interpreter
        to be notified that the object has a Python-defined method to call. With only
        __getattribute_ _ defined, that notification doesn't happen for all of the other
        magic methods).

        This actually makes sense - otherwise how would the method which implements
        __getattribute_ _ be retrieved?

        Similarly, in the existing recipe, none of __init__, __call__, __coerce__ or
        __getattr__ are delegated - the behaviour is actually consistent for all magic
        methods (I'm curious how the existing recipe actually works - it seems the use
        of "self.runfu nc" in __call__ should get delegated. It obviously isn't, though).

        Something like the following might work (I haven't tested it though):

        class Deferred(object ):
        ...

        def lookup_magic(f_ name):
        def new_f(self, *args, **kwargs):
        return getattr(self, f_name)(*args, **kwargs)
        return new_f

        func_list = ['__add__', '__radd__', ...]
        for f_name in func_list:
        setattr(Deferre d, f_name) = lookup_magic(f_ name)

        A metaclass may actually provide a cleaner solution, but I'm not quite sure
        where to start with that.

        Cheers,
        Nick.

        --
        Nick Coghlan | ncoghlan@email. com | Brisbane, Australia
        ---------------------------------------------------------------

        Comment

        Working...