I would like to be able to define a different class method, depending on whether one of the inputs is present or not. Something like:
class mcmc(object):
def __init__(self, X, Y=None):
if Y is None:
def input_vector(self, beta):
return beta.dot(X)
else:
def input_vector(self, beta):
return beta.dot(np.vstack([X, Y]))
I could have coded this directly in the method, like:
class mcmc(object):
def __init__(self, X, Y=None):
self.X = X
if Y is not None:
self.Y = Y
def input_vector(self, beta):
if self.__hasattr__('Y'):
return return beta.dot(np.vstack([self.X, self.Y]))
else:
return beta.dot(self.X)
but the function is used repeatedly (millions of times), so it probably adds a lot to the execution time.
Another similar possibility, inspired by How can I call any method inside a class depending on an input to another method in the same class?, is probably:
class mcmc(object):
def __init__(self, X, Y=None):
self.X = X
if Y is not None:
self.Y = Y
self.method = 'input_vector_XY'
else:
self.method = 'input_vector_X'
def input_vector(self, beta):
return self.__getattribute__(self.method)(beta)
def input_vector_XY(self, beta):
return return beta.dot(np.vstack([self.X, self.Y]))
def input_vector_X(self, beta):
return beta.dot(self.X)
This also involves an “overhead” in terms of calling an additional function.
10
In order to avoid making the decision each time input_vector
is called, instead of doing this on the instance level you could do it on the class level by defining two different classes (maybe with a common base class to avoid duplicating features), and make mcmc
a factory function which returns an instance of one or the other class:
def mcmc(X, Y=None):
if Y is None:
return MCMCWithoutY(X)
else:
return MCMCWithY(X, Y)
class BaseMCMC:
def __init__(self, X):
self.X = X
def common_features(args):
# do something
def input_vector(self, beta):
# must be implemented in derived classes
# alternatively, provide a default implementation
raise NotImplementedError
class MCMCWithoutY(BaseMCMC):
def input_vector(self, beta):
return beta.dot(self.X)
class MCMCWithY(BaseMCMC):
def __init__(self, X, Y):
super().__init__(X)
self.Y = Y
def input_vector(self, beta):
return beta.dot(np.vstack([self.X, self.Y]))
2
The solution that you already mentioned in your question can be improved a bit, and after that your requirements should be satisfied
class mcmc(object):
def __init__(self, X, Y=None):
self.X = X
self.input_vector = self.input_vector_X
if Y is not None:
self.Y = Y
self.input_vector = self.input_vector_XY
def input_vector_XY(self, beta):
return beta.dot(np.vstack([self.X, self.Y]))
def input_vector_X(self, beta):
return beta.dot(self.X)
m = mcmc(X=X, Y=None)
m.input_vector(beta)
The downside, is that you won’t receive help from IDE about self.input_vector
, or automatic documentation generation, because it is not true method of the class defined by def
. It’s just a variable containing reference to the method