当订单很重要时,处理参数以便在Python中进行预处理

时间:2014-01-16 00:28:23

标签: python function arguments

我想对有关外观顺序的命名变量有所作为。

我希望有一个关于编辑图像的管道,这对我应用的技术有所不同。我不想单独调用函数,而是还想使用包装函数。

例如:

def preprocess(cutoff=None, resize=None, blur=None):
    ....

现在,如果我将此功能称为preprocess(resize=(100, 100), cutoff=55),我首先要resize,然后执行切断,但在preprocess(cutoff=55, resize=(100,100))时反之亦然。

实现这一目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

您无法使用关键字参数。如果您通过正常参数接受它们,就像您尝试过的那样,唯一的顺序是参数的顺序。如果您通过**kwargs接受,则会获得dict(没有订单)。

如果你想知道参数的顺序,它们必须是位置参数;真的没办法解决这个问题。

然而,可能有更好的设计。例如,为什么不让它们分开?然后,而不是:

newfoo = foo.preprocess(resize=(100, 100), cutoff=55)

...你这样做:

newfoo = foo.resize(100, 100).cutoff(55)

或提供简单的类型,除了包装参数外什么也不做:

newfoo = foo.preprocess(Resize(100, 100), Cutoff(55))

然后,您可以让preprocess通过*args获取参数并根据type(arg)发送。


如果你看看你如何实现它,它指出了另一种可能性:

class DumbArgWrapper(object):
    def __init__(self, *args):
        self.args = args

class Resize(DumbArgWrapper): pass
class Cutoff(DumbArgWrapper): pass
class Blur(DumbArgWrapper): pass

class ImageProcessor(object):
    def preprocess(self, *args):
        for arg in args:
            if isinstance(arg, Resize):
                do_resize(*arg.args)
            # etc.

如果您只是将do_resize代码移动到Resize(换句话说,使其成为一种“懒惰函数”对象),它会更清晰:

class SmartArgWrapper(object):
    def __init__(self, *args):
        self.args = args

class Resize(SmartArgWrapper):
    def __call__(self, target):
        do_resize(target, *self.args)
# etc.

class ImageProcessor(object):
    def preprocess(self, *args):
        for arg in args:
            arg(self)

完成后,您可以创建一个简单的包装器,将任何函数转换为SmartArtWrapper,而不是创建一堆子类。

然后......


关键是,有很多可能性。对于那些知道你想要什么和为什么的人来说,应该只有一种明显的方法可以做到这一点......但是对于那些不知道你想要什么和为什么的人来说,这是不正确的。