生成元组的修改副本

generate a modified copy of a tuple

我知道我不能修改元组,我已经看到了从另一个元组创建元组的方法,手动连接原始元组的各个部分,例如 here

但想知道是否已经出现了一些 pythonic 方法来 'modify' 一个元组,通过隐式创建一个新元组,比如

>>> source_tuple = ('this', 'is', 'the', 'old', 'tuple')
>>> new_tuple = source_tuple.replace(3, 'new')
>>> new_tuple
('this', 'is', 'the', 'new', 'tuple')

一个可能的实现可能看起来像这样,但我正在寻找一个内置解决方案:

def replace_at(source, index, value):
    if isinstance(source, tuple):
        return source[:index] + (value,) + source[index + 1:]
    elif isinstance(source, list):
        return source[:index] + [value,] + source[index + 1:]
    else:
        explode()

实现这样的功能并不需要太多工作,但就像 Enum 已经证明的那样,有时实现每个人都使用会更好..

编辑:我的目标是而不是替换源元组。我知道我可以使用列表,但即使在这种情况下,我也会先制作一份副本。所以我真的只是在寻找一种创建修改副本的方法。

你可以使用某种理解:

source_tuple = ('this', 'is', 'the', 'old', 'tuple')
new_tuple = tuple((value if x != 3 else 'new'
                   for x, value in enumerate(source_tuple)))
# ('this', 'is', 'the', 'new', 'tuple')

在这种情况下,这是相当愚蠢的,但可以让您了解一般概念。最好使用 list,但毕竟您可以在此处更改基于索引的值。

如果你需要用替换的元素创建新的元组,你可以使用这样的东西:

def replace_value_in_tuple(t, ind, value):
    return tuple(
        map(lambda i: value if i == ind else t[i], range(len(t)))
    )

您可以在元组上使用切片(产生新的元组)并连接:

>>> x=3
>>> new_tuple=source_tuple[0:x]+('new',)+source_tuple[x+1:]
>>> new_tuple
('this', 'is', 'the', 'new', 'tuple')

然后您可以像这样支持列表或元组:

>>> def replace_at(source, index, value):
...     return source[0:index]+type(source)((value,))+source[index+1:]
...
>>> replace_at([1,2,3],1,'new')
[1, 'new', 3]
>>> replace_at((1,2,3),1,'new')
(1, 'new', 3)

或者,直接在列表上进行:

>>> source_tuple = ('this', 'is', 'the', 'old', 'tuple')
>>> li=list(source_tuple)
>>> li[3]='new'
>>> new_tuple=tuple(li)
>>> new_tuple
('this', 'is', 'the', 'new', 'tuple')

如评论中所述——这就是列表的用途...

如果您正在考虑即时交换值,那么 list 是更合适的数据结构;正如我们已经知道的,元组是 不可变的.

另一方面,如果您要在 tuple 中寻找 交换值 逻辑,您可以查看 collections.namedtuple有一个 _replace 方法。

They can be used wherever regular tuples are used

>>> source_tuple = ('this', 'is', 'the', 'old', 'tuple')

>>> Factory = namedtuple('Factory', range(5), rename=True)

>>> source_tuple = Factory(*source_tuple)

>>> source_tuple
Factory(_0='this', _1='is', _2='the', _3='old', _4='tuple')

>>> new_tuple = source_tuple._replace(_3='new')

>>> new_tuple
Factory(_0='this', _1='is', _2='the', _3='new', _4='tuple')

嗯,这看起来不太优雅。我仍然建议您改用 list