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
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.
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`.
> 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
On Wed, Sep 12, 2012 at 4:22 AM, pyjoshsys <j.m.dagenh...@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
> 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.dagenh...@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.