想在 Python 中定义一些我最好称之为“函数扩展”/“函数接口(interface)”或“函数类”的东西。还没有在其他语言中看到类似的结构,但我不是像 LISP 这样的函数式语言的专家。如果这更容易做到,考虑以后改用其他语言,例如 Julia。
“函数扩展”将是一种正式的方式来表达绑定(bind)函数的几个参数,我们最终得到一个属于特定“函数类”的函数。在我下面的例子中,特定的“函数类”是一个数据转换函数(如 transform_data_func_class ),它有一个唯一的参数: data . power_data延伸transform_data_func_class作为绑定(bind) exponent参数我们最终得到一个属于“函数类”的函数transform_data_func_class .
“函数类”定义了签名的一部分,例如:
def transform_data_func_class(data):
raise InterfaceError('Called unimplemented function class.')
然后将定义扩展“函数类”的函数:
def power_data(data, exponent): # extends: transform_data_func_class
return data ** exponent # apply the additional the parameter
因此,当绑定(bind)附加参数时,我们最终会得到一个与扩展的“函数类”相匹配的签名:
square = partial(power_data, exponent=2) # matches signature transform_data_func_class(data)
我将使用这些作为示例,以便将函数类型指定为其他函数的输入和输出:
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."""
...
奇怪的是,虽然在一般对象的情况下定义类/类型相对容易,但在函数的情况下却没有这样明显的构造。目前我使用extends: function_class用于指定函数类型/类的注释 - 从 mypy 中借用的想法- 理想情况下会使用更正式的东西。
欢迎提出任何建议,如果我可以通过 __call__ 调用生成的构造,那就太好了.想到了这样一个类:
class TransformDataFuncClass(object):
@classmethod
def exec(cls, data):
raise InterfaceError('Called unimplemented function class.')
但不喜欢无意义的 exec() 调用。也想到了:
class TransformDataFuncClass(object):
@classmethod
def __call__(cls, data):
raise InterfaceError('Called unimplemented function class.')
但我得到 TypeError: object() takes no parameters打电话时 TransformDataFuncClass(data=1) .通过类继承发出“功能扩展”信号将是一个很好的方法。
我最详尽的计划是:
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
所以TransformDataFuncClass(data=1)和 PowerData(data=1, exponent=2)是自然而有效的电话。虽然后者实际上有点复杂,并且无法并行计算,因为我从 dill 得到了错误。 (一个更聪明的替代 pickle )说 <class PowerData>: it's not the same object as PowerData .
真的,欢迎任何建议。我也对理论考虑以及如何用其他语言完成这一点很感兴趣。
请您参考如下方法:
很难看出您要完成什么。具体来说,对于这两个函数定义:
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
power_data如何扩展transform_data_interface?它们没有相同的签名:“接口(interface)”采用单个参数,而实现接口(interface)的函数采用两个。这与大多数人所说的 interface 不符。 .
如果您要做的是强制给定函数具有与另一个函数相同的参数和返回值,您可以通过检查函数的参数来实现。
- inspect stdlib 中的模块可以告诉您函数采用哪些参数,具体来说,Signatures为此提供一个不错的 API
- function annotations允许您标记函数的参数和返回值,这可以用
"# extends:"注释替换您要执行的操作 - 另见 new proposal on using function annotations for optional typing和 mypy
- 装饰器是添加这种检查的完美场所,因为它在函数执行前包装函数,很多人已经制作了类型检查装饰器(示例:1、2、3)<
对于您的chain 功能,请参阅Composing functions in python .您可以修改其中一个以执行我上面提到的那种检查。
至于其他更具功能性的语言如何做这种事情,我不确定。我看到 type classes在我上面链接的那篇界面文章中提到,看起来那里有一些很好的信息。
如果您有更多关于您尝试做的事情的细节或背景,请更新您的帖子!
