这很可能是某种东西的复制品,但是我的serach foo让我失望。
众所周知,元组是不可变的,所以你无法真正改变它们。但是,有时候,为了改变(1, 2, "three")
到(1, 2, 3)
而做一些事情会很方便,或许与Haskell record update syntax.类似。你实际上不会改变原始元组,但你会得到一个 new 只有一个(或多个)元素不同的元素。
这样做的方法是:
elements = list(old_tuple)
elements[-1] = do_things_to(elements[-1])
new_tuple = tuple(elements)
我觉得将一个元组更改为一个列表但是有点违背了使用old_tuple
的元组类型开头的目的:如果你使用的是列表,那么你就不必构建一个每次操作内存中元组的丢弃列表副本。
如果你要更改,比如说,只改变元组的第3个元素,你也可以这样做:
def update_third_element(a, b, c, *others):
c = do_things_to(c)
return tuple(a, b, c, *others)
new_tuple = update_third_element(*old_tuple)
这将比天真的方法更能抵制元组中元素数量的变化:
a, b, c, d, e, f, g, h, i, j = old_tuple
c = do_things_to(c)
new_tuple = (a, b, c, d, e, f, g, h, j, j) # whoops
...但是如果您想要更改的是最后一个,或者 n -th到最后一个元素,则它不起作用。它还会创建一个抛弃列表(others
)。它还会强制您将所有元素命名为 n -th。
有更好的方法吗?
答案 0 :(得分:2)
我会改用collections.namedtuple
:
>>> from collections import namedtuple
>>> class Foo(namedtuple("Foo", ["a", "b", "c"])):
pass
>>> f = Foo(1, 2, 3) # or Foo(a=1, b=2, c=3)
>>> f._replace(a = 5)
Foo(a=5, b=2, c=3)
namedtuple
也支持索引,因此您可以使用它们代替普通元组。
如果必须使用普通元组,只需使用辅助函数:
>>> def updated(tpl, i, val):
return tpl[:i] + (val,) + tpl[i + 1:]
>>> tpl = (1, 2, 3)
>>> updated(tpl, 1, 5)
(1, 5, 3)