返回仅允许命名参数的函数

时间:2017-09-19 21:19:36

标签: python python-3.x scipy

我使用python3脚本插入一些测量数据。为此,我想编写一个函数,它返回插值函数。此插值函数应仅采用某个命名参数。这是我到目前为止所提出的简化版本:

    from scipy.interpolate import interp1d

    x = [1, 2]
    y = [1, 3]

    def linear_interp(x, y):
        # Interpolate the data
        y_interp = interp1d(x, y)

        # Create a function taking only a named argument x
        def y_interp_named(*, x):
            return y_interp(x)

        return y_interp_named

    y_linear_interp = linear_interp(x, y)

    print(y_linear_interp(x = 1.5)) # This should work
    print(y_linear_interp(1.5))     # This should throw an error

虽然这是按预期工作的,但我想知道它是否可以在不使用函数y_interp_named的情况下以更优雅/更紧凑的方式实现。

一般情况下:对于返回另一个函数的函数,有没有办法指定返回的函数只应该采用除返回函数定义之外的某些命名参数?

3 个答案:

答案 0 :(得分:2)

您可以使用python的decorators做类似的事情。

$('input[type=radio]').click(function() {
    if($(this).data('previously-checked')) {
        alert('Already Selected');
    }
    // update all as not clicked
    $('input[type=radio]').data('previously-checked', false);
    // mark current one as checked
    $(this).data('previously-checked', true);
})

编辑:您也可以像这样使用装饰器:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form method='get' action=''>
    <input type="radio" name="radiobutton" value="Y">
    <input type="radio" name="radiobutton" value="Y">
    <input type="radio" name="radiobutton" value="Y">
</form>

答案 1 :(得分:0)

我喜欢@FlashTek的答案,但lambda可能是另一种选择。

return lambda *, x: y_interp(x)

此外,如果你要在多于一个地方使用它,你可以创建一个装饰器,使函数的所有参数都只是关键字。不幸的是,我对此并不了解,因此它在装饰函数中删除了任何默认参数值。

import types

def kwonly(func):
    code = types.CodeType(
        0, # new co_argcount
        func.__code__.co_argcount + func.__code__.co_kwonlyargcount, # new co_kwonlyargcount
        func.__code__.co_nlocals,
        func.__code__.co_stacksize,
        func.__code__.co_flags,
        func.__code__.co_code,
        func.__code__.co_consts,
        func.__code__.co_names,
        func.__code__.co_varnames,
        func.__code__.co_filename,
        func.__code__.co_name,
        func.__code__.co_firstlineno,
        func.__code__.co_lnotab,
        func.__code__.co_freevars,
        func.__code__.co_cellvars
    )
    return types.FunctionType(code, func.__globals__, func.__name__)

但是,在您的情况下,它可以用作

return kwonly(y_interp)

答案 2 :(得分:0)

  

指定...函数应该只接受某些命名参数

我四处搜索&#34;强制执行argspec&#34;,&#34;强制执行呼叫规范&#34;,&#34;混淆argspec&#34;以及其他变种但没有运气。

类似的东西可以用类来完成:你可以判断优雅/紧凑。

这是Python 2.7代码,我认为3.6有细微差别,我会在3.6时更新。

from scipy import interpolate
class F(object):
    '''Given X values, iterpolate Y values.'''
    def __init__(self, x, y):
        self.interp = interpolate.interp1d(x, y)
    def __call__(self, **kw):
        try:
            arg = kw['x']
            return self.interp(arg)
        except KeyError as e:
            #something appropriate here
            raise TypeError('x only', e)

用法

>>> f = F([1,2],[1,3])
>>> f(x = [1.1,1.11,1.22])
array([ 1.2 ,  1.22,  1.44])

>>> f(y = [1.1,1.11,1.22])

Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    f(y = [1.1,1.11,1.22])
  File "P:\pyProjects\tmp.py", line 26, in __call__
    raise TypeError('x only', e)
TypeError: ('x only', KeyError('x',))
>>>

>>> f([1.1,1.11,1.22])

Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    f([1.1,1.11,1.22])
TypeError: __call__() takes exactly 1 argument (2 given)
>>>

另一种选择是定义可接受关键字的类属性,然后测试成员资格:

class F(object):
    acceptable = {'x','a'}
    def __init__(self, x, y):
        self.interp = interpolate.interp1d(x, y)
    def __call__(self, **kw):
        if not self.acceptable.issuperset(kw):
            #something appropriate here
            difference = set(kw).difference(self.acceptable)
            raise TypeError('invalid keyword argument',
                            str((list(difference))))
        arg = kw['x']
        return self.interp(arg)