I am trying to make my new code as user friendly as possible and what I would have in mind for the particular problem I am facing atm is this:
Suppose we have
import numpy as np
class TestClass:
def __init__(self, data):
self.data = data
@property
def method_a(self):
return np.median(self.data)
@property
def method_b(self):
return np.mean(self.data)
foo = TestClass([1, 2, 5, 7, 12, 6, 3, 37, 16])
print(foo.method_a)
print(foo.method_b)
Everything is fine so far. Method A gives me the median, method B the mean.
During processing I will switch depending on circumstances between both methods. So sometimes I will call method A, sometimes method B. However, what I want is then to continue with a method C, that acts upon the result of either method A or B in such a way
final_result = foo.method_a.method_c
or
final_result = foo.method_b.method_c
I know it is possible to write method C as a function and do it like this:
final_result = method_c(foo.method_a)
final_result = method_c(foo.method_b)
but I think it would make the code easier to read if I could apply method C as stated above.
Is this possible somehow?
thanks
3 Answers 3
your statement is not quite clear, let's assume you want to add method C to the class. you can wrap your return value inside of the class again to achieve what you want:
import numpy as np
class TestClass:
def __init__(self, _data):
self._data = data
@property
def data(self): return self._data
@property
def method_a(self):
return TestClass(np.median(self.data))
@property
def method_b(self):
return TestClass(np.mean(self.data))
@property
def method_c(self):
return TestClass(np.whatever(self.data))
then you can chain however long you want:
final_result = foo.method_a.method_b.method_c.method_c.data
if the class is not what you plan to place, you put different one.
1 Comment
Following HuStmpHrrr's comment I changed my code like this (Here I just assume that method C simply adds 1 to the results):
import numpy as np
class NewClass:
def __init__(self, data):
self.data = data
def method_c(self):
return self.data + 1
class TestClass:
def __init__(self, data):
self.data = data
@property
def method_a(self):
return NewClass(np.median(self.data))
@property
def method_b(self):
return NewClass(np.mean(self.data))
foo = TestClass([1, 2, 5, 7, 12, 6, 3, 37, 16])
result1 = foo.method_a
result2 = foo.method_b
print(result1.method_c())
print(result2.method_c())
Comments
I'm not sure why you want a property. Your code seems like it really just needs a simple method. Properties are for data that you would get and set that you want to manage.
class Test(Object):
def __init__(self, data):
super().__init__()
self.data = data
self.value = 0
# end Constructor
def method_a(self):
return np.median(self.data)
# end method_a
@property
def method_c(self):
return self.value
@method_c.setter
def method_c(self, value):
self.value = value
# self.method_a(value)
# end method_c
# end class Test
t = Test([1,2,3,4])
print(t.method_a())
t.method_c = 5 # This calls the method_c.setter and will make t.value = 5
print(t.method_c)
The property is typically used as a wrapper method to control the data.
meanandmedian, why not wrap it first before returning?method_aormethod_bwithout then callingmethod_con the result?method_aandmethod_bare returning a simple number, andmethod_cwould take that number as a parameter. Your proposed change would mean making a whole new class, or adding state toTestClass, just to enable call-chaining. You would be adding complexity to the implementation of the method, for what's a very debatable increase in readability of the call. Personally, I prefer using parameters and return values over object state whenever appropriate. The rules are a little different at API surfaces, but to make an API friendly you'd ideally only expose one method.