Here is the use case.
class EvaluateCustomMethod(object):
faker = Faker()
def __init__(self, custom_method, cardinality=1):
self.custom_method = custom_method
self.cardinality = cardinality
@property
def random_first_name(self):
return self.faker.first.name()
def call_method_n_times(self):
return [getattr(self, self.custom_method) \
for _ in range(self.cardinality)]
f = EvaluateCustomMethod('random_first_name', 1)
f.call_method_n_times()
I am trying to find a way where I do not have to make a method call after instantiating an object and achieve my goal directly when I create an instance.
My ultimate goal is this:
{"test" : {"name" : EvaluateCustomMethod('random_first_name', 1)}}
This is linked to a previous question
1 Answer 1
The answer which follows is a don't, since wanting to do what is proposed is very likely to be a strong signal of refactoring need.
One possibility is to use the constructor __new__, so as to determine what is going to be returned when you instantiate the class. As follows
class EvaluateCustomMethod(object):
faker = Faker()
def __new__(cls, custom_method, cardinality=1):
instance = super(EvaluateCustomMethod, cls).__new__(cls)
instance.custom_method = custom_method
instance.cardinality = cardinality
return instance.call_method_n_times()
@property
def random_first_name(self):
return self.faker.first.name()
def call_method_n_times(self):
return [getattr(self, self.custom_method) \
for _ in range(self.cardinality)]
Which would return
>>> EvaluateCustomMethod('random_first_name', 1)
['John']
>>> {"test" : {"name" : EvaluateCustomMethod('random_first_name', 1)}}
{"test" : {"name" : ['Jack']}}
But actually, overriding
__new__ like so is so discouraged, that what you may want to do, more classically, is
class EvaluateCustomMethod(object):
faker = Faker()
def __init__(self, custom_method, cardinality=1):
self.custom_method = custom_method
self.cardinality = cardinality
@property
def random_first_name(self):
return self.faker.first.name()
def call_method_n_times(self):
return [getattr(self, self.custom_method) \
for _ in range(self.cardinality)]
def __call__(self):
return self.call_method_n_times()
Which returns the same thing, but doing exactly what one thinks it does
>>> EvaluateCustomMethod('random_first_name', 1)
['Jacques']
>>> {"test" : {"name" : EvaluateCustomMethod('random_first_name', 1)()}}
{"test" : {"name" : ['Richard']}}
4 Comments
foo = Foo(), (almost) instantaneously, written on your own or not, __new__ is called and returns something: an object with methodes and attributes attached. When one override __new__, as above, we make the class actually returning what we exactly tell it to return. In our case, it returns the list returned by the methode you choose to call.
__new__method). Just refactor EvaluateCustomMethod into a function.