Reputation: 10996
I am trying to implement multiple constructors in python and one of the suggestions (through online searching) was to use the classmethod. However, using this, I am having issues with code reuse and modularity. Here is an example where I can create an object based on a supplied file or through some other means:
class Image:
def __init__(self, filename):
self.image = lib.load(filename)
self.init_others()
@classmethod
def from_data(cls, data, header):
cls.image = lib.from_data(data, header)
cls.init_others()
return cos
def init_others(self):
# initialise some other variables
self.something = numpy.matrix(4,4)
Now it seems that I cannot do that. The cls.init_others() call fails by saying that I have not provided the object to call it on. I guess I can initialise things in the from_data function itself but then I repeat the code in the init method and the other "constructors". Does anyone know how I can call these other initialiser methods from these @classmethod marked functions? Or perhaps someone knows a better way to initialise these variables.
I come from a C++ background. So still trying to find my way around the python constructs.
Upvotes: 1
Views: 2138
Reputation: 122032
Your class method should create and return a new instance of the class, not assign class attributes and return the class itself. As an alternative to the keyword arguments, you could do something like:
class Image:
def __init__(self, image):
self.image = image
self.init_others()
@classmethod
def from_data(cls, data, header):
return cls(lib.from_data(data, header))
@classmethod
def from_filename(cls, filename):
return cls(lib.load(filename))
def init_others(self):
# initialise some other variables
self.something = numpy.matrix(4, 4)
This adds the ability to create an instance if you already have the image
, too.
Upvotes: 2
Reputation: 94891
I would recommend not trying to create multiple constructors, and use keyword arguments instead:
class Image(object):
def __init__(self, filename=None, data=None, header=None):
if filename is not None:
self.image = lib.load(filename)
elif data is not None and header is not None:
self.image = lib.from_data(data, header)
else:
raise ValueError("You must provide filename or both data and header")
self.init_others()
def init_others(self):
# initialise some other variables
self.something = numpy.matrix(4,4)
This is a more Pythonic way to handle this scenario.
Upvotes: 2
Reputation: 6935
You should always pass in self
as the first argument to any method that will act on a class instance. Python will not automatically determine the instance you're trying to call the method for unless you do that. So if you want to use a class function like
the_image = Image("file.txt")
the_image.interpolate(foo,bar)
You need to define the method within Image
as
def interpolate(self,foo,bar):
# Your code
Upvotes: 1