Python API设计中的重载(或替代) [英] Overloading (or alternatives) in Python API design

查看:81
本文介绍了Python API设计中的重载(或替代)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个现有的大型程序库,当前具有.NET绑定,并且我正在考虑编写Python绑定.现有的API广泛使用了基于签名的重载.因此,我有大量的静态函数,例如:

I have a large existing program library that currently has a .NET binding, and I'm thinking about writing a Python binding. The existing API makes extensive use of signature-based overloading. So, I have a large collection of static functions like:

Circle(p1, p2, p3) -- Creates a circle through three points
Circle(p, r)       -- Creates a circle with given center point and radius
Circle(c1, c2, c3) -- Creates a circle tangent to three curves

在某些情况下,必须以不同的方式使用相同的输入,因此基于签名的重载不起作用,而我必须使用不同的函数名.例如

There are a few cases where the same inputs must be used in different ways, so signature-based overloading doesn't work, and I have to use different function names, instead. For example

BezierCurve(p1,p2,p3,p4) -- Bezier curve using given points as control points
BezierCurveThroughPoints(p1,p2,p3,p4) -- Bezier curve passing through given points

我想第二种技术(使用不同的函数名)可以在Python API中的任何地方使用.所以,我会

I suppose this second technique (using different function names) could be used everywhere in the Python API. So, I would have

CircleThroughThreePoints(p1, p2, p3)
CircleCenterRadius(p, r)
CircleTangentThreeCurves(c1, c2, c3)

但是名称看起来太冗长(我不喜欢缩写),发明所有这些名称将是一个很大的挑战,因为该库具有成千上万个函数.

But the names look unpleasantly verbose (I don't like abbreviations), and inventing all of them will be quite a challenge, because the library has thousands of functions.

低优先级:
努力(就我而言)-我不在乎是否必须编写大量代码.
性能

Low Priorities:
Effort (on my part) -- I don't care if I have to write a lot of code.
Performance

高优先级:
易于使用/了解呼叫者(许多人将是编程新手).
我很容易写出好的文档.
简单-避免在调用方代码中使用高级概念.

High Priorities:
Ease of use/understanding for callers (many will be programming newbies).
Easy for me to write good documentation.
Simplicity -- avoid the need for advanced concepts in caller's code.

我确定我不是第一个希望在Python中基于签名的重载的人.人们通常使用哪些变通办法?

I'm sure I'm not the first person who ever wished for signature-based overloading in Python. What work-arounds do people typically use?

推荐答案

一种选择是在构造函数中排他地使用关键字参数,并包括确定应该使用的逻辑:

One option is to exclusively keyword arguments in the constructor, and include logic to figure out what should be used:

class Circle(object):
    def __init__(self, points=(), radius=None, curves=()):
        if radius and len(points) == 1:
            center_point = points[0]
            # Create from radius/center point
        elif curves and len(curves) == 3:
            # create from curves
        elif points and len(points) == 3:
            # create from points
        else:
            raise ValueError("Must provide a tuple of three points, a point and a radius, or a tuple of three curves)

您还可以使用类方法使API用户更轻松:

You can also use classmethods to make things easier for the users of the API:

class Circle(object):
    def __init__(self, points=(), radius=None, curves=()):
         # same as above

    @classmethod
    def from_points(p1, p2, p3):
        return cls(points=(p1, p2, p3))

    @classmethod
    def from_point_and_radius(cls, point, radius):
        return cls(points=(point,), radius=radius)

    @classmethod
    def from_curves(cls, c1, c2, c3):
        return cls(curves=(c1, c2, c3))

用法:

c = Circle.from_points(p1, p2, p3)
c = Circle.from_point_and_radius(p1, r)
c = Circle.from_curves(c1, c2, c3)

这篇关于Python API设计中的重载(或替代)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆