Reputation: 2429
I'm implementing several constructors using @classobj
. I'm not only setting variables, but also calling methods in the new class:
class Example:
def __init__(self):
pass
@classmethod
def constructor1(cls,x,y):
self=cls
self.__x = x
self.__somemethod(self,y)
...
I get the following error:
unbound method __somemethod() must be called with Example instance as
first argument (got classobj instance instead)
How do I resolve this problem?
Upvotes: 1
Views: 731
Reputation: 12158
looks like __somemethod
is not a classmethod, but a "normal" method.
And normal methods expect an actual instance as the first parameter, not a class.
And because constructor1
is decorated as a @classmethod
, cls
is the class itself - which you pass to __somemethod
.
That cannot work.
You should reconsider your design approach.
Addendum:
Maybe you meant something like this?
@classmethod
def constructor1(cls, x, y):
newinst = cls()
newinst.__x = x
cls.__somemethod(newinst, y)
That'd be better written as followed, though:
@classmethod
def constructor1(cls, x, y):
newinst = cls()
newinst.__x = x
newinst.__somemethod(y)
actually, I like neighter approach - seems like a codesmell of overcomplexity to me.
Upvotes: 2
Reputation: 104712
If you're wanting your class method to be a constructor, you probably want to be creating an instance of the class you get passed in as cls
. I suspect you're trying to do that with your self = cls
line, but you're not actually creating a new instance because you've neglected to put parentheses. There are some other issues too, but I think that is the key one. Here's a fixed constructor:
@classmethod
def constructor1(cls,x,y):
self=cls() # parentheses added, to make it a call
self.__x = x
self.__somemethod(y) # self is not needed as a parameter here
return self # return the new instance
Upvotes: 3
Reputation: 2429
Thanks to ch3ka's answer and Tim Pietzcker's comment, I found my error: I used the factory method from http://jjinux.blogspot.co.at/2008/11/python-class-methods-make-good.html and forgot the ()
in the line self=cls()
. Now it works just fine:
class Example:
def __init__(self):
pass
@classmethod
def constructor1(cls,x,y):
self=cls()
self.__x = x
self.__somemethod(self,y)
...
Upvotes: 1
Reputation: 142156
This may be a template of what I think you're trying to achieve...
import random
class Something(object):
def __init__(self, value, **kwargs):
self.value = value
for k, v in kwargs.iteritems():
setattr(self, k, v)
@classmethod
def from_iterable(cls, iterable):
return cls(sum(iterable), description='came from from_iterable')
@classmethod
def make_random(cls):
return cls(random.randint(1,1000), is_random=True)
a = Something.from_iterable([1, 2, 3])
b = Something.make_random()
c = Something(56)
for obj in (a, b, c):
print type(obj), obj.value
<class '__main__.Something'> 6
<class '__main__.Something'> 308
<class '__main__.Something'> 56
Upvotes: 1