【发布时间】:2015-04-16 04:57:22
【问题描述】:
想在 Python 中定义一些我最好称之为“函数扩展”/“函数接口”或“函数类”的东西。还没有在其他语言中看到类似的结构,但我不是 LISP 等函数式语言的专家。如果这更容易做到,考虑稍后更改为其他语言,比如在 Julia 中。
“函数扩展”将是一种正式的方式来表达绑定一个函数的几个参数,我们最终得到一个属于特定“函数类”的函数。在我下面的示例中,特定的“函数类”是一个数据转换函数(如transform_data_func_class),它有一个唯一的参数:data。 power_data 扩展 transform_data_func_class 作为绑定 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
因此,当绑定附加参数时,我们最终会得到一个与扩展的“函数类”匹配的签名:
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 cmets 来指定函数类型/类——这是从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.')
但我在拨打TransformDataFuncClass(data=1) 时收到TypeError: object() takes no parameters。不过,通过类继承发出“功能扩展”信号将是一种好方法。
我最详尽的计划是:
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。
欢迎任何建议,真的。我也对理论上的考虑以及在其他语言中如何做到这一点感兴趣。
【问题讨论】:
-
这与函数重载有何不同?
-
我需要几个具有相同(或扩展)签名但名称不同的函数。 “函数重载或方法重载是创建具有不同实现的多个同名方法的能力”。假设
MultiplyData(data, param1)与PowerData(data, param1)具有相同的签名。我正在寻找的更像是对象的接口/抽象类。一旦你修复了一个类的移动部分,它就会匹配继承的接口。 -
当然有点超出我的预期,我的第一直觉是建议一个元类,但我确信我没有完全掌握这个概念 - 虽然这些可能是一个开始......A quest for pythonic interfaces和A Primer on Python Metaclasses
标签: python types lambda functional-programming lambda-calculus