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

How to (re)define function with complex argument

我在 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 函数即可。

这是一个装饰器方法。坐标检测不是很智能,你可能想磨练一下:

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)