3

假设您正在编写一个打算公开的 API。API 中的函数quux返回一个列表或元组生成器,例如yield (foo, bar).

客户端代码通常会像这样使用它:

for foo, bar in quux(whatever):
    # do stuff with foo and bar

现在,假设将来您可能想开始与和baz一起返回。你现在不想退回它,因为 YAGNI 直到证明不是这样。foobar

(尝试)确保未来这样的更改不会破坏客户端代码的最佳方法是什么?

我知道 Python 3 允许人们做类似的事情,for foo, bar, *idontcare in quux(whatever)并且在 Python 2 中,人们总是可以编写一个实用函数(像这样使用for foo, bar in iterleft(quux(whatever), 2)):

def iterleft(iterable, limit):
    for item in iterable:
        yield item[:limit]

但我想知道是否有更好的方法来做这样的事情。

4

2 回答 2

5

问题是您有没有与数据一起传递的语义数据(“元组的第一个元素表示 x,第二个元素表示 y,...”)。

解决此问题的通用方法是返回{"foo": foo, "bar": bar, ...}参数字典。当然,那么你不能使用元组解包。

否则,为了保持向后兼容性,您无法更改quux. 相反,您可以编写quux_with_bar生成(foo, bar, baz)元组,然后quux只过滤其中的前两个元素。

于 2012-11-20T14:31:42.660 回答
4

返回 anamedtuple而不是常规元组,您不需要解包它。然后您可以在不影响 API 的现有用户的情况下扩展返回的元组:

from collections import namedtuple

QuuxReturnValue = namedtuple('QuuxReturnValue', ('foo', 'bar'))

def quux(*args, **kw):
    while True:
        yield QuuxReturnValue(foo='foo', bar='bar')

并且您的 API 的使用方式如下:

for retval in quux():
    print retval.foo, retval.bar

如果您稍后更新namedtuple以添加第三个参数'baz',则上述使用者仍然可以工作。

于 2012-11-20T16:26:11.567 回答