如何(重新)定义具有复杂参数的函数

时间:2017-03-05 10:19:55

标签: python function arguments svgwrite

我在Python中使用svgwrite库,因为svg有y轴向下,而我觉得向上移动更方便,我定义了一个函数YInvert,这对我来说很有用。但是,每次使用svgwrite中的函数时,我都必须使用此函数,例如:

dwg.line((xI,YInvert(yI)), (xII,YInvert(yII)), stroke='blue', stroke_width=0.1)

但是,这很不舒服。我如何重新定义函数dwg.line(或定义一些新函数LineNew)以自动包含YInvert?我希望论证的形式相同,我的意思是我可以使用:

dwg.line((xI,yI), (xII,yII), stroke='blue', stroke_width=0.1)

LineNew((xI,yI), (xII,yII), stroke='blue', stroke_width=0.1)

我也用例如

dwg.circle(center=(10,YInvert(10)), r=0.2, fill='black')

所以我正在寻找适用于各种参数的东西,只需在正确的位置添加YInvert函数。

1 个答案:

答案 0 :(得分:2)

这是一个装饰方法。坐标检测不是很聪明,你可能想要磨练一点:

from functools import wraps

def YInvert(Y): # just for demo
    return -Y

def invert_axis(f):
    @wraps(f)
    def g(*args, **kwds):
        args = list(args)
        for j, a in enumerate(args):
            if isinstance(a, tuple) and len(a) == 2:
                try:
                    args[j] = (a[0], YInvert(a[1]))
                except:
                    pass
        for k, v in kwds.items():
            if isinstance(v, tuple) and len(v) == 2:
                try:
                    kwds[k] = (v[0], YInvert(v[1]))
                except:
                    pass
        return f(*args, **kwds)
    return g

演示:

@invert_axis
def f(a, b, c, d=3):
    print(a, b, c, d)

f((1, 2), 3, (4, 5), d=(1, 2))
# (1, -2) 3 (4, -5) (1, -2)

这也可以应用于已经定义的函数,如库函数:

f2 = invert_axis(f2)