Suppose I have class Function
, whose instances are callables that take one argument. I defined pointwise arithmetic for these classes in the straightforward way. Here's a simplified version of my code (I actually have more complex behavior in __init__
and __call__
but it's irrelevant for this question):
class Function:
'''
>>> f = Function(lambda x : x**2)
>>> g = Function(lambda x : x + 4)
>>> h = f/g
>>> h(6)
3.6
'''
def __init__(self, func):
self.func = func
def __call__(self, value):
return self.func(value)
def __truediv__(self, other):
if isinstance(other, Function):
return Function(lambda x:self(x)/other(x))
else:
return NotImplemented
# ...
I'm stuck when I try to allow implicit type conversions. For example, I want to be able to write:
>>> f = Function(lambda x : x ** 2)
>>> g = f+1
>>> g(5)
26
In other words, whenever I see a numeric object v
in an arithmetic expression next to a Function
instance, I want to convert v
to Function(lambda x : v)
.
In addition, I want to achieve similar behavior for some of my user-defined types (again, whenever I see them in the same binary arithmetic expression with a Function
object).
While I can certainly code this logic with a brute force assortment of regular and reflected binary arithmetic operators, each checking isinstance(v, numbers.Number)
, and isinstance(v, MyUserDefinedType)
, I feel there might be a more elegant way.
Also, if there are any other improvements possible with my design, please let me know. (Function
objects are created rarely, but called very often, so performance is of some interest.)
EDIT:
To address @Eric's comment, I should clarify that I have another user-defined class Functional
:
class Functional:
'''
>>> c = [1, 2, 3]
>>> f = Functional(lambda x : x + 1)
>>> f(c)
[2, 3, 4]
>>> g = Functional(lambda x : x ** 2)
>>> h = f + g
>>> h(c)
[3, 7, 13]
'''
def __init__(self, func):
self.func = func
@staticmethod
def from_function(self, function):
return Functional(function.func)
def __call__(self, container):
return type(container)(self.func(c) for c in container)
def __add__(self, other):
if isinstance(other, Functional):
return Functional(lambda x : self.func(x) + other.func(x))
else:
return NotImplemented
When I see both a Function
and a Functional
instance in the same arithmetic expression, I want Function
to be implicitly converted to Functional
using Functional.from_function
method.
So, implicit type conversion hierarchy goes like this:
And I'd like to implicitly convert to the highest type in this hierarchy seen in a given arithmetic expression.
Something like this for all operators would work well:
def __truediv__(self, other):
if callable(other):
return Function(lambda x:self(x)/other(x))
else:
return Function(lambda x:self(x)/other)