我想对有关外观顺序的命名变量有所作为。
我希望有一个关于编辑图像的管道,这对我应用的技术有所不同。我不想单独调用函数,而是还想使用包装函数。
例如:
def preprocess(cutoff=None, resize=None, blur=None):
....
现在,如果我将此功能称为preprocess(resize=(100, 100), cutoff=55)
,我首先要resize
,然后执行切断,但在preprocess(cutoff=55, resize=(100,100))
时反之亦然。
实现这一目标的最佳方法是什么?
答案 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
,而不是创建一堆子类。
然后......
关键是,有很多可能性。对于那些知道你想要什么和为什么的人来说,应该只有一种明显的方法可以做到这一点......但是对于那些不知道你想要什么和为什么的人来说,这是不正确的。