Python:改变元组中的值

我是python的新手,所以这个问题可能有点基础。 我有一个称为values的元组,其中包含以下内容:

 ('275', '54000', '0.0', '5000.0', '0.0') 

我想改变这个元组中的第一个值(即275 ),但我知道元组是不可变的,所以values[0] = 200将不起作用。 我怎样才能做到这一点?

首先你需要问,你为什么要这么做?

但是可以通过:

 t = ('275', '54000', '0.0', '5000.0', '0.0') lst = list(t) lst[0] = '300' t = tuple(lst) 

但是如果你需要改变一些东西的话,那么最好把它保存为一个list

根据你的问题切片可以是一个非常整洁的解决scheme:

 >>> b = (1, 2, 3, 4, 5) >>> b[:2] + (8,9) + b[3:] (1, 2, 8, 9, 4, 5) >>> b[:2] + (8,) + b[3:] (1, 2, 8, 4, 5) 

这允许你添加多个元素或者replace一些元素(特别是如果它们是“邻居”的话)。在上面的例子中,转换为列表可能更合适,更易读(即使切片符号更短)。

那么,正如Trufa已经表明的那样,基本上有两种方法来replace给定索引处的元组元素。 将元组转换为列表,replace元素并转换回来,或者通过串联构造一个新的元组。

 In [1]: def replace_at_index1(tup, ix, val): ...: lst = list(tup) ...: lst[ix] = val ...: return tuple(lst) ...: In [2]: def replace_at_index2(tup, ix, val): ...: return tup[:ix] + (val,) + tup[ix+1:] ...: 

那么,哪个方法更好,那就更快了?

事实certificate,对于短元组(在Python 3.3中),连接实际上更快!

 In [3]: d = tuple(range(10)) In [4]: %timeit replace_at_index1(d, 5, 99) 1000000 loops, best of 3: 872 ns per loop In [5]: %timeit replace_at_index2(d, 5, 99) 1000000 loops, best of 3: 642 ns per loop 

然而,如果我们查看更长的元组,列表转换就是要走的路:

 In [6]: k = tuple(range(1000)) In [7]: %timeit replace_at_index1(k, 500, 99) 100000 loops, best of 3: 9.08 µs per loop In [8]: %timeit replace_at_index2(k, 500, 99) 100000 loops, best of 3: 10.1 µs per loop 

对于很长的元组,列表转换实际上更好!

 In [9]: m = tuple(range(1000000)) In [10]: %timeit replace_at_index1(m, 500000, 99) 10 loops, best of 3: 26.6 ms per loop In [11]: %timeit replace_at_index2(m, 500000, 99) 10 loops, best of 3: 35.9 ms per loop 

而且,连接方法的性能取决于我们replace元素的索引。 对于列表方法,索引是不相关的。

 In [12]: %timeit replace_at_index1(m, 900000, 99) 10 loops, best of 3: 26.6 ms per loop In [13]: %timeit replace_at_index2(m, 900000, 99) 10 loops, best of 3: 49.2 ms per loop 

所以:如果你的元组很短,分片和连接。 如果它很长,做清单转换!

不是说这是优越的,但如果有人好奇,可以在一行上完成:

 tuple = tuple([200 if i == 0 else _ for i, _ in enumerate(tuple)]) 

编辑:这不适用于重复条目的元组呢!

基于Pooya的想法 :

如果你打算经常这样做(你不应该这样做,因为元组因为某种原因不能修改),你应该这样做:

 def modTupByIndex(tup, index, ins): return tuple(tup[0:index]) + (ins,) + tuple(tup[index+1:]) print modTupByIndex((1,2,3),2,"a") 

或者基于Jon的想法 :

 def modTupByIndex(tup, index, ins): lst = list(tup) lst[index] = ins return tuple(lst) print modTupByIndex((1,2,3),1,"a") 

基于Jon的想法和亲爱的Trufa

 def modifyTuple(tup, oldval, newval): lst=list(tup) for i in range(tup.count(oldval)): index = lst.index(oldval) lst[index]=newval return tuple(lst) print modTupByIndex((1, 1, 3), 1, "a") 

它会更改所有旧值的发生

正如Hunter McMillen在评论中所写的那样,元组是不可变的,所以你需要创build一个新的元组来实现这个function。 例如:

 >>> tpl = ('275', '54000', '0.0', '5000.0', '0.0') >>> change_value = 200 >>> tpl = (change_value,) + tpl[1:] >>> tpl (200, '54000', '0.0', '5000.0', '0.0') 

你不能。 如果你想改变它,你需要使用一个列表,而不是一个元组。

请注意,您可以改为创build一个具有新值的新元组作为其第一个元素。

我发现编辑元组的最好方法是使用以前的版本作为基础重新创build元组。

下面是一个例子,我用它来制作一个颜色较浅的版本(当时我已经打开了):

 colour = tuple([c+50 for c in colour]) 

它是做什么的,它是通过元组“颜色”读取每个项目,做一些事情,最后把它添加到新的元组中。

所以你想要的会是这样的:

 values = ('275', '54000', '0.0', '5000.0', '0.0') values = (tuple(for i in values: if i = 0: i = 200 else i = values[i]) 

那个具体的一个不起作用,但是这个概念就是你所需要的。

 tuple = (0, 1, 2) 

元组=遍历元组,根据需要更改每个项目

这是概念。

首先,问问你自己为什么要改变你的tuple有一个原因,为什么string和元组在Ptyhon中是不可变的 ,如果你想改变你的tuple那么它应该可能是一个list

其次,如果你仍然想改变你的元组,那么你可以将你的tuple转换成一个list然后将其转换回来,并将新元组重新分配给相同的variables。 如果你只是要改变你的元组一次,这是很好的。 否则,我个人认为这是违反直觉的。 因为它基本上是创build一个新的元组,每次如果你想改变元组,你将不得不执行转换。 另外,如果你阅读代码,那么为什么不创build一个list呢? 但这很好,因为它不需要任何库。

我build议使用mutabletuple(typename, field_names, default=MtNoDefault) 。 我个人认为这种方式更直观 可读。 个人阅读代码会知道作家打算在未来变异这个元组。 与上面的list转换方法相比,缺点是这需要你导入额外的py文件。

 from mutabletuple import mutabletuple myTuple = mutabletuple('myTuple', 'vwxy z') p = myTuple('275', '54000', '0.0', '5000.0', '0.0') print(pv) #print 275 pv = '200' #mutate myTuple print(pv) #print 200 

TL; DR :不要试图改变tuple 。 如果你这样做,它是一次性操作将tuple转换为列表,将它改变,将list变成一个新的tuple ,并重新分配回旧的tuplevariables。 如果愿望tuple并以某种方式想要避免list并想多次mutate,然后创buildmutabletuple

我相信这在技术上回答了这个问题,但是不要在家里这样做。 目前,所有的答案都涉及到创build一个新的元组,但是你可以使用ctypes来修改内存中的元组。 依靠64位系统上CPython的各种实现细节,一种方法如下:

 def modify_tuple(t, idx, new_value): # `id` happens to give the memory address in CPython; you may # want to use `ctypes.addressof` instead. element_ptr = (ctypes.c_longlong).from_address(id(t) + (3 + idx)*8) element_ptr.value = id(new_value) # Manually increment the reference count to `new_value` to pretend that # this is not a terrible idea. ref_count = (ctypes.c_longlong).from_address(id(new_value)) ref_count.value += 1 t = (10, 20, 30) modify_tuple(t, 1, 50) # t is now (10, 50, 30) modify_tuple(t, -1, 50) # Will probably your crash Python runtime 

我做到了这一点:

 list = [1,2,3,4,5] tuple = (list) 

并改变,只是做

 list[0]=6 

你可以改变一个元组:D

这是从IDLE完全复制

 >>> list=[1,2,3,4,5,6,7,8,9] >>> tuple=(list) >>> print(tuple) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list[0]=6 >>> print(tuple) [6, 2, 3, 4, 5, 6, 7, 8, 9]