You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python工具包API设计:多途经点支持下采用坐标元组列表作为参数是否符合Python风格?

关于Python工具包cartons路由API多途经点设计的疑问

我开发了一款名为cartons的Python工具包,封装了RoutingPy与OSRM库。目前路由API的调用形式是:cartons.route(lon1, lat1, lon2, lat2)。现在规划1.2.0版本迭代,想给这个API新增多途经点支持,考虑把API调整成接收坐标元组列表的形式:cartons.route(coords_lon_lat),其中coords_lon_lat是类似[(lon1, lat1), (lon2, lat2), (lon3, lat3)]的元组列表。想请教这个设计方案是不是优质且符合Python风格(Pythonic)的选择,有没有更优的API结构设计方案?

附GitHub仓库示例代码:
routing.py

from routingpy import OSRM
def route(base_url, coords_lon_lat:list, transport):
    router = OSRM(base_url=base_url)
    route = router.directions(
        overview = "full",
        profile = transport,
        locations = coords_lon_lat
    )
    return route

我的分析与建议

首先要给你的初始方案点个赞——这个设计完全符合Python风格!用列表包裹元组的方式传递多组坐标,既直观又贴合Python处理结构化数据的习惯,而且和你底层调用的router.directions的locations参数格式完全对齐,省去了额外的格式转换,代码简洁易维护。

不过,为了让API更健壮、易用,这里还有几个优化方向可以参考:

1. 兼容旧API,实现平滑过渡

如果你的工具包已经有用户在使用,直接修改API签名会导致老代码报错。可以通过参数判断来兼容两种调用方式:

from routingpy import OSRM
from typing import List, Tuple, Union

def route(base_url: str, coords: Union[List[Tuple[float, float]], float], *args, transport: str):
    # 处理两种输入格式
    if isinstance(coords, list):
        coords_lon_lat = coords
    else:
        # 旧格式:lon1, lat1, lon2, lat2...
        if len(args) < 3 or (len(args) + 1) % 2 != 0:
            raise ValueError("For legacy format, provide pairs of lon/lat: lon1, lat1, lon2, lat2...")
        coords_lon_lat = [(coords, args[0])] + list(zip(args[1::2], args[2::2]))
    
    # 参数验证
    if len(coords_lon_lat) < 2:
        raise ValueError("At least two coordinates (start and end) are required.")
    
    router = OSRM(base_url=base_url)
    return router.directions(
        overview="full",
        profile=transport,
        locations=coords_lon_lat
    )

这样老用户的cartons.route(base_url, lon1, lat1, lon2, lat2, transport="driving")依然能用,新用户则可以用cartons.route(base_url, [(lon1, lat1), (lon2, lat2), (lon3, lat3)], transport="driving"),兼顾了兼容性和新功能。

2. 完善类型提示,提升开发体验

给参数加上更精确的类型提示,能让IDE自动补全和错误检查,这也是现代Python的最佳实践之一。比如把coords_lon_lat:list改成coords_lon_lat: List[Tuple[float, float]],明确告诉用户每个元素是包含两个数值的元组。

3. 增加参数验证,提前规避错误

在函数开头对输入的坐标列表做简单验证,比如检查列表长度至少为2(必须有起点和终点)、每个元组都是数值类型,这样能提前给出清晰的错误提示,而不是让底层库抛出模糊的异常,提升用户排查问题的效率:

def route(base_url: str, coords_lon_lat: List[Tuple[float, float]], transport: str):
    # 验证坐标列表长度
    if len(coords_lon_lat) < 2:
        raise ValueError("At least two coordinates (start and end) are required.")
    # 验证每个坐标的格式
    for idx, (lon, lat) in enumerate(coords_lon_lat):
        if not isinstance(lon, (int, float)) or not isinstance(lat, (int, float)):
            raise TypeError(f"Coordinate at index {idx} must be a tuple of numbers, got ({type(lon).__name__}, {type(lat).__name__})")
    
    # 后续逻辑...

4. 把可选参数设为关键字参数

像transport、overview这类可选参数,建议设为带默认值的关键字参数,这样用户调用时不用记忆参数顺序,也能按需调整:

def route(base_url: str, coords_lon_lat: List[Tuple[float, float]], transport: str = "driving", overview: str = "full"):
    router = OSRM(base_url=base_url)
    return router.directions(
        overview=overview,
        profile=transport,
        locations=coords_lon_lat
    )

用户可以根据需要灵活传递参数:cartons.route(my_base_url, my_coords, transport="walking")或者cartons.route(my_base_url, my_coords, overview="simplified")。

总结

你的初始设计是非常Pythonic的核心思路,在此基础上加上兼容性处理、类型提示和参数验证,就能打造出一个既易用又健壮的API。如果团队内部使用或者用户群体比较新,也可以直接采用新的列表格式,简化API的复杂度——具体要看你的用户场景和需求哦。

内容的提问来源于stack exchange,提问作者Andrej Bajusic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 09:57:29