Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #28921 > unrolled thread

generators as decorators simple issue

Started byj.m.dagenhart@gmail.com
First post2012-09-11 19:28 -0700
Last post2012-09-12 04:15 -0700
Articles 8 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  generators as decorators simple issue j.m.dagenhart@gmail.com - 2012-09-11 19:28 -0700
    Re: generators as decorators simple issue Ramchandra Apte <maniandram01@gmail.com> - 2012-09-11 19:55 -0700
    Re: generators as decorators simple issue alex23 <wuwei23@gmail.com> - 2012-09-11 21:39 -0700
    Re: generators as decorators simple issue Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2012-09-12 08:08 +0200
    Re: generators as decorators simple issue pyjoshsys <j.m.dagenhart@gmail.com> - 2012-09-12 03:22 -0700
      Re: generators as decorators simple issue Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2012-09-12 11:47 +0100
      Re: generators as decorators simple issue Ian Kelly <ian.g.kelly@gmail.com> - 2012-09-12 09:09 -0600
    Re: generators as decorators simple issue pyjoshsys <j.m.dagenhart@gmail.com> - 2012-09-12 04:15 -0700

#28921 — generators as decorators simple issue

Fromj.m.dagenhart@gmail.com
Date2012-09-11 19:28 -0700
Subjectgenerators as decorators simple issue
Message-ID<e738542a-f864-4ad0-9aaa-738047356841@googlegroups.com>
I'm trying to call SetName on an object to prevent me from ever having to call it explictly again on that object. Best explained by example.


def setname(cls):
    '''this is the proposed generator to call SetName on the object'''
    try:
        cls.SetName(cls.__name__)
    finally:
        yield cls


class Trial:
    '''class to demonstrate with'''
    def SetName(self, name):
        print 1, 1

@setname
class Test(Trial):
    '''i want SetName to be called by using setname as a decorator'''
    def __init__(self):

        print 'Yay! or Invalid.'

if __name__ == '__main__':
    test = Test()


How can i fix this? 
This is my exact error: python decors2.py 
Traceback (most recent call last):
  File "decors2.py", line 23, in <module>
    test = Test()
TypeError: 'generator' object is not callable

[toc] | [next] | [standalone]


#28922

FromRamchandra Apte <maniandram01@gmail.com>
Date2012-09-11 19:55 -0700
Message-ID<9ead5a5c-2fe0-44ce-9d90-13e19b95d31e@googlegroups.com>
In reply to#28921
On Wednesday, 12 September 2012 07:58:10 UTC+5:30, pyjoshsys  wrote:
> I'm trying to call SetName on an object to prevent me from ever having to call it explictly again on that object. Best explained by example.
>
[snip]
In your decorator, you are using `yield cls` - it should be `return cls` 99.99% of the time.

[toc] | [prev] | [next] | [standalone]


#28928

Fromalex23 <wuwei23@gmail.com>
Date2012-09-11 21:39 -0700
Message-ID<14d034e0-d477-4cde-8a7c-1f31f2e68ee2@v19g2000pbt.googlegroups.com>
In reply to#28921
On Sep 12, 12:28 pm, j.m.dagenh...@gmail.com wrote:
> def setname(cls):
>     '''this is the proposed generator to call SetName on the object'''
>     try:
>         cls.SetName(cls.__name__)
>     finally:
>         yield cls

A generator is (basically) a callable that acts like an iterator.
You'd use a generator if you wanted to loop with for or a list
comprehension across the output of the generator: for foo in
setname(Test)

A decorator is a callable that takes another callable as an argument,
either modifying it or returning a wrapped version of it: Test =
setname(Test)

You don't want to iterate over anything, so you should change `yield`
to `return`.

[toc] | [prev] | [next] | [standalone]


#28931

FromThomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de>
Date2012-09-12 08:08 +0200
Message-ID<k2p8s7$jlc$1@r03.glglgl.gl>
In reply to#28921
Am 12.09.2012 04:28 schrieb j.m.dagenhart@gmail.com:
> I'm trying to call SetName on an object to prevent me from ever having to call it explictly again on that object. Best explained by example.
>
>
> def setname(cls):
>      '''this is the proposed generator to call SetName on the object'''
>      try:
>          cls.SetName(cls.__name__)
>      finally:
>          yield cls
>
>
> class Trial:
>      '''class to demonstrate with'''
>      def SetName(self, name):
>          print 1, 1
>
> @setname
> class Test(Trial):
>      '''i want SetName to be called by using setname as a decorator'''
>      def __init__(self):
>
>          print 'Yay! or Invalid.'
>
> if __name__ == '__main__':
>      test = Test()
>
>
> How can i fix this?

I am not sure what exactly you want to achieve, but I see 2 problems here:

1. Your setname operates on a class, but your SetName() is an instance 
function.

2. I don't really understand the try...finally yield stuff. As others 
already said, you probably just want to return. I don't see what a 
generator would be useful for here...

def setname(cls):
      '''this is the proposed generator to call SetName on the object'''
      try:
          cls.SetName(cls.__name__)
      finally:
          return cls

and

class Trial(object):
     '''class to demonstrate with'''
     @classmethod
     def SetName(cls, name):
         print 1, 1

should solve your problems.

[toc] | [prev] | [next] | [standalone]


#28942

Frompyjoshsys <j.m.dagenhart@gmail.com>
Date2012-09-12 03:22 -0700
Message-ID<3ffa457e-7836-46d0-8246-03b6bd90a025@googlegroups.com>
In reply to#28921
The output is still not what I want. Now runtime error free, however the output is not what I desire.



def setname(cls):
    '''this is the proposed generator to call SetName on the object'''
    
    try:
        cls.SetName(cls.__name__)
    except Exception as e:
        print e
    finally:
        return cls

class Trial(object):
    '''class to demonstrate with'''
    def __init__(self):
        object.__init__(self)
        self.name = None
    
    @classmethod
    def SetName(cls, name):
        cls.name = name

@setname
class Test(Trial):
    '''i want SetName to be called by using setname as a decorator'''
    def __init__(self):
        Trial.__init__(self)

        

if __name__ == '__main__':
    test = Test()
    print 'instance'
    print '', test.name #should be Test
    print 'class'
    print '', Test.name
    

The output is: python decors2.py 
instance
 None
class
 Test

I want: 
instance
 Test
class
 Test

Is this possible in this manner?

[toc] | [prev] | [next] | [standalone]


#28943

FromOscar Benjamin <oscar.j.benjamin@gmail.com>
Date2012-09-12 11:47 +0100
Message-ID<mailman.547.1347446843.27098.python-list@python.org>
In reply to#28942
On Wed, 12 Sep 2012 03:22:31 -0700 (PDT), pyjoshsys 
<j.m.dagenhart@gmail.com> wrote:
> The output is still not what I want. Now runtime error free, 
however the output is not what I desire.

> def setname(cls):
>     '''this is the proposed generator to call SetName on the 
object'''

>     try:
>         cls.SetName(cls.__name__)
>     except Exception as e:
>         print e
>     finally:
>         return cls

I would write the function above in one line:

cls.name = name


> class Trial(object):
>     '''class to demonstrate with'''
>     def __init__(self):
>         object.__init__(self)
>         self.name = None

Remove the line above. The instance attribute self.name is hiding the 
class attribute cls.name.

Oscar

[toc] | [prev] | [next] | [standalone]


#28972

FromIan Kelly <ian.g.kelly@gmail.com>
Date2012-09-12 09:09 -0600
Message-ID<mailman.566.1347462581.27098.python-list@python.org>
In reply to#28942
On Wed, Sep 12, 2012 at 4:22 AM, pyjoshsys <j.m.dagenhart@gmail.com> wrote:
> The output is still not what I want. Now runtime error free, however the output is not what I desire.

[SNIP]

> class Trial(object):
>     '''class to demonstrate with'''
>     def __init__(self):
>         object.__init__(self)
>         self.name = None
>
>     @classmethod
>     def SetName(cls, name):
>         cls.name = name

[SNIP]

> if __name__ == '__main__':
>     test = Test()
>     print 'instance'
>     print '', test.name #should be Test
>     print 'class'
>     print '', Test.name
>
>
> The output is: python decors2.py
> instance
>  None
> class
>  Test
>
> I want:
> instance
>  Test
> class
>  Test
>
> Is this possible in this manner?


The SetName class method sets the name on the *class* dictionary.  The
class's __init__ method also sets a name (None) on the *instance*
dictionary.  From an instance's perspective, the instance dictionary
will shadow the class dictionary.  If you remove the attribute from
the instance dictionary entirely (delete the "self.name = None" line),
and leave the class dictionary as is, then you will get the output you
want (although from your later post I am not certain that this is the
behaviour you want).


On Wed, Sep 12, 2012 at 5:15 AM, pyjoshsys <j.m.dagenhart@gmail.com> wrote:
> so decorators only pass the object and not any instance of the object as the implied argument? Is this right?

Right.

> The idea was to use @setname instead of instance.SetName(instance.__name__).

The appropriate place to do this so that it applies to all instances
of the class rather than to the class would be inside the __init__
method.

Also, instances don't have a __name__ attribute, so it's still unclear
to me what you're looking for.  Did you mean the effect to be that of
"instance.SetName(cls.__name__)"?  If so, then the decorator approach
(with the line "self.name = None" removed) should be fine for your
purposes -- you'll just have the name stored in the class dict instead
of in each instance dict, but it will still be visible as long as you
haven't shadowed it.

[toc] | [prev] | [next] | [standalone]


#28946

Frompyjoshsys <j.m.dagenhart@gmail.com>
Date2012-09-12 04:15 -0700
Message-ID<eb154bbe-8836-431f-831e-8763544b1c54@googlegroups.com>
In reply to#28921
so decorators only pass the object and not any instance of the object as the implied argument? Is this right?

The idea was to use @setname instead of instance.SetName(instance.__name__).

I thought decorators would do this, but it seems not.






[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web