Would like to define something I'd best call 'function extension' / 'function interface' or 'class of functions' in Python. Haven't seen similar constructs in other languages, but I'm no expert in functional languages like LISP. Considering to change to other language later if this is easier to do, say in Julia.
'Function extension' would be a formal way to express that binding few arguments of a function, we end up with a function belonging to a specific 'class of functions'. In my examples below the specific 'class of functions' is a data transformation function (as transform_data_func_class
), which has a sole argument: data
. power_data
extends transform_data_func_class
as binding the exponent
argument we end up with a function which belongs to the the 'class of functions' transform_data_func_class
.
A 'class of functions' defines part of the signature like:
def transform_data_func_class(data):
raise InterfaceError('Called unimplemented function class.')
Then would define functions extending the 'class of functions':
def power_data(data, exponent): # extends: transform_data_func_class
return data ** exponent # apply the additional the parameter
So that when binding the additional parameter(s) we end up with a signature matching that of the extended 'class of functions':
square = partial(power_data, exponent=2) # matches signature transform_data_func_class(data)
I'll use these for example, in order to specify types of functions as inputs and outputs of other functions:
def chain(data, transform_data_func_class_list):
"""Passing in data and a list of functions being elements of
transform_data_func_class with a sole argument: data."""
...
Find it odd that while in the case of general objects it is relatively easy to define classes/types, in case of functions there is no such obvious construct. Currently I use extends: function_class
comments to specify function types/classes - an idea borrowed from mypy
- ideally would use something more formal.
Any suggestions welcome, would be great if I could just call the resulting construct through __call__
. Have thought of a class like:
class TransformDataFuncClass(object):
@classmethod
def exec(cls, data):
raise InterfaceError('Called unimplemented function class.')
But don't like the ununtiutive exec() call. Have also thought of:
class TransformDataFuncClass(object):
@classmethod
def __call__(cls, data):
raise InterfaceError('Called unimplemented function class.')
but I get TypeError: object() takes no parameters
when calling TransformDataFuncClass(data=1)
. Signaling 'function extension' through class inheritence would be a great way though.
My most elaborate plan was to do:
class FuncClass(object):
"""Takes care of function classes and extensions being
just callable through __call__, e.g. PowerData(data=1, power=2)
instead of instantiating first: PowerData()(data=1, power=2)"""
def __init__(self, wrapped_class):
self.wrapped_class = wrapped_class
self.wrapped_instance = wrapped_class()
def __call__(self, *args, **kwargs):
return self.wrapped_instance(*args, **kwargs)
@FuncClass
class TransformDataFuncClass(object):
def __call__(self, data):
raise InterfaceError('Called unimplemented function class.')
@FuncClass
class PowerData(TransformDataFuncClass.wrapped_class):
def __call__(self, data, exponent):
return data ** exponent # apply the additional the parameter
So that TransformDataFuncClass(data=1)
and PowerData(data=1, exponent=2)
are natural and valid calls. While the latter actually worked its a bit complicated, and couldn't parallelize calculations as I got errors from dill
(an smarter alternative to pickle
) saying that <class PowerData>: it's not the same object as PowerData
.
Any suggestions welcome, really. I'm also interested in theoretical considerations and how this is done in other languages.
It's a little hard to see what you're trying to accomplish. Specifically, for these two function definitions:
def transform_data_interface(data):
raise InterfaceError('Called unimplemented interface.')
def power_data(data, param1): # extends: transform_data_interface
return data ** param1 # apply the additional the parameter
How does power_data
extend transform_data_interface
? They don't have the same signature: the "interface" takes a single argument, while the function implementing the interface takes two. That doesn't match what most people would say is an interface .
If what you're trying to do is enforce that a given function has the same arguments and return value as another function, you can accomplish this by inspecting the function's arguments.
"# extends:"
comment For your chain
function, see Composing functions in python . You can modify one of those to also do the kind of checking I mentioned above.
As far as how other more functional languages do this kind of thing, I'm not sure. I see type classes mentioned in that interface article I linked to above, looks like there's some good info there.
If you have more specifics or background on what you're trying to do please update your post!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.