简体   繁体   English

在Python中,为同一事物的不同类型使用两个参数还是处理多个类型的一个参数更好?

[英]In Python, is it better to have two parameters for different types of the same thing, or handle one parameter of multiple types?

Please help resolve this debate on my team: 请帮助解决有关我团队的辩论:

If we have a function that takes either a point (list of 3 values) or a list of points, then we have either: 如果我们有一个采用一个点(3个值的列表)或一个点列表的函数,则我们可以:

def f(point=None, points=None):
    if points is None: points = []
    if point is not None: points.append(point)
    .... stuff with "points" ....

or 要么

def g(points):
    if len(points) > 0 and not isinstance(points[0],list):
        points = [points]
    .... stuff with "points" ....

to be called as, 被称为

x = f(points=[[1,2,3],[4,5,6]])
y = f(point=[1,2,3])
z = g(points=[[1,2,3],[4,5,6]])
w = g(points=[1,2,3])

where x,y,z, and w should all be the same (if f and g are the same function). 其中x,y,z和w应该都相同(如果f和g是相同的函数)。

That is to say, internally both f and g want a 2-dimensional array, but provide mechanisms to accept a single-dimensional array. 也就是说,在内部, fg需要一个二维数组,但是提供了接受一维数组的机制。

The difference is that f has an argument for each type, and therefore each argument expects a single, specific type, but g has a single argument that may be of multiple types. 区别在于f对每种类型都有一个参数,因此每个参数都需要一个特定的类型,而g具有一个可能为多种类型的参数。

The question is, which style is more "Pythonic"? 问题是,哪种风格更“ Pythonic”? (References to PEPs more than welcome.. I couldn't find anything.) (对PEP的引用不受欢迎。。我什么都找不到。)

Edit: I forgot to mention that ostensibly the reason for supporting 1-dimensional input is backwards compatibility. 编辑:我忘了提到表面上支持一维输入的原因是向后兼容。 That is to say, f(point, axis) already exists, and we are changing it to f(points, axes) .. and we are trying to changing the callers as they are external to this code base. 也就是说, f(point, axis)已经存在,并且我们将其更改为f(points, axes) ..并且我们试图更改调用者,因为它们在此代码库的外部。 I agree that perhaps the right answer is to not do this at all and force the caller to be consistent with their types, but I ask the reader to assume this would be difficult and to provide some clarity on the two choices I am asking about, if at all possible. 我同意,也许正确的答案是完全执行此操作,并迫使呼叫者与他们的类型保持一致,但是我请读者假设这将很困难,并且在我要问的两个选择中提供了一些清晰的说明,如果可能的话。 Thanks! 谢谢!

As the signatures of your f and g differ, I'm assuming you control how the function is or will be called. 由于fg的签名不同,我假设您控制函数的调用方式或调用方式。 In this case, the most logical thing to do would be to accept only two dimensional lists and call it like this: 在这种情况下,最合乎逻辑的事情是仅接受二维列表并按如下方式调用它:

x = h([[1,2,3], [4,5,6]])
y = h([[1,2,3]])

A list of points with only one element is no special case unless it is semantically diferent than a multipoint list in your context or it would change the functions behavior. 仅包含一个元素的点的列表不是特殊情况,除非在语义上与上下文中的多点列表不同,否则它将改变函数的行为。

I'd suggest using *args (or, well, call it *points possibly) and making the user unpack his points on his end. 我建议使用* args (或者,可以将其称为* points),并让用户在自己的末端解压缩他的点。

This allows you to call f(point) , f(point1, point2, point3) , or f(*list_of_points) , with all three options working fine and you can simply do: 这使您可以调用f(point)f(point1,point2,point3)f(* list_of_points) ,并且所有三个选项都可以正常工作,您可以简单地执行以下操作:

def f(*points):
    ...
    for point in points:
        do_pointy_stuff(point)

...which is similar to g2 but without hacky isinstance checks which would fail if someone decided to throw in a tuple or something instead. ...类似于g2,但是没有进行过强力的isinstance检查,如果有人决定放入元组或其他内容,则检查失败。

However, there is a minor potential pitfall here - the user must knowingly unpack his lists of points. 但是,这里存在一个潜在的小陷阱-用户必须有意识地打开他的点列表。 If you don't pay attention when using a single argument, you may pass a *[points] rather than a *[[list of points]], which would result in the function treating each coordinate as a separate argument in itself and most likely throwing an error. 如果您在使用单个参数时不注意,则可以传递* [points]而不是* [[points]],这将导致函数将每个坐标本身和大多数坐标作为单独的参数可能会引发错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM