Answers:
首先,您需要问,为什么要这样做?
但是可以通过:
t = ('275', '54000', '0.0', '5000.0', '0.0')
lst = list(t)
lst[0] = '300'
t = tuple(lst)
但是,如果您需要进行更改,最好将其保留为 list
好吧,正如Trufa已经显示的那样,在给定的索引上基本上有两种替换元组元素的方法。将元组转换为列表,替换元素然后再转换回去,或者通过串联构造新的元组。
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:]
...:
那么,哪种方法更好,那就是更快?
事实证明,对于短元组(在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
同样,串联方法的性能取决于替换元素的索引。对于列表方法,索引是不相关的。
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
因此:如果您的元组很短,则切片并连接。如果很长,请执行列表转换!
一个衬垫是可能的:
values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])
values
?
i = 2; values = (*values[:i], '300', *values[i+1:])
我相信这从技术上讲可以回答问题,但不要在家中这样做。目前,所有答案都涉及创建新的元组,但是您可以使用它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 crash your Python runtime
编辑:这不适用于具有重复条目的元组!
基于Pooya的想法:
如果您打算经常执行此操作(由于元组由于某种原因是不变的,则不应该这样做),您应该执行以下操作:
def modTupByIndex(tup, index, ins):
return tuple(tup[0:index]) + (ins,) + tuple(tup[index+1:])
print modTupByIndex((1,2,3),2,"a")
或基于乔恩的想法:
def modTupByIndex(tup, index, ins):
lst = list(tup)
lst[index] = ins
return tuple(lst)
print modTupByIndex((1,2,3),1,"a")
第一拳,问自己为什么要突变你的tuple
。在Ptyhon中,字符串和元组是不可变的,这是有原因的,如果您想对自己的变量进行突变,tuple
那么它应该是一个list
替代。
其次,如果您仍然希望对元组进行突变,则可以将转换tuple
为,list
然后再转换回去,然后将新的元组重新分配给相同的变量。如果您只想对元组进行一次变异,那就太好了。否则,我个人认为这是违反直觉的。因为它本质上是在创建一个新的元组,并且每次您想要对元组进行突变时,都必须执行转换。另外,如果您阅读了代码,那么思考为什么不仅仅创建一个list
?但这很好,因为它不需要任何库。
我建议mutabletuple(typename, field_names, default=MtNoDefault)
从mutabletuple 0.2使用。我个人认为这种方式是一个更直观和可读性。阅读该代码的人会知道编写者打算将来更改此元组。与list
上面的转换方法相比,不利之处在于,这需要您导入其他py文件。
from mutabletuple import mutabletuple
myTuple = mutabletuple('myTuple', 'v w x y z')
p = myTuple('275', '54000', '0.0', '5000.0', '0.0')
print(p.v) #print 275
p.v = '200' #mutate myTuple
print(p.v) #print 200
TL; DR:不要尝试变异tuple
。如果您这样做并且是一次操作,则转换tuple
为列表,对其进行变异,将其list
转换为新tuple
变量,然后重新分配给持有old的变量tuple
。如果欲望tuple
和某种原因想避免list
并想变异多于一次,那就创造mutabletuple
。
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")
它会改变您所有的旧价值观
我发现编辑元组的最佳方法是使用以前的版本作为基础来重新创建元组。
这是我用来制作较浅颜色的示例(当时我已经打开它了):
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)
元组=遍历元组,根据需要更改每个项目
这就是概念。
我来晚了,但是我认为最简单,资源友好和最快的方法(取决于情况)是覆盖元组本身。由于这将消除对列表和变量创建的需要,因此将其归档在一行中。
new = 24
t = (1, 2, 3)
t = (t[0],t[1],new)
>>> (1, 2, 24)
但是:这仅适用于较小的元组,并且还会将您限制为固定的元组值,但是,无论如何,在大多数情况下,这都是元组的情况。
因此,在这种特殊情况下,它看起来像这样:
new = '200'
t = ('275', '54000', '0.0', '5000.0', '0.0')
t = (new, t[1], t[2], t[3], t[4])
>>> ('200', '54000', '0.0', '5000.0', '0.0')
tldr; “解决方法”是创建一个新的元组对象,而不是实际修改原始对象
尽管这是一个非常老的问题,但有人告诉我有关Python变异元组的疯狂。我非常惊讶/被它吸引,并做了一些谷歌搜索,我降落在这里(和其他在线的类似样本)
我进行了一些测试以证明我的理论
请注意==
,值相等,而is
引用相等(obj a与obj b相同)
a = ("apple", "canana", "cherry")
b = tuple(["apple", "canana", "cherry"])
c = a
print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))
d = list(a)
d[1] = "kiwi"
a = tuple(d)
print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))
产量:
a: ('apple', 'canana', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: True
b == c :: True
a == c :: True
a is b :: False
b is c :: False
a is c :: True
a: ('apple', 'kiwi', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: False
b == c :: True
a == c :: False
a is b :: False
b is c :: False
a is c :: False
我这样做:
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]
x = (y)
除了将y赋给x以外,什么都不做。
您可以使用按引用复制来更改元组的值
>>> tuple1=[20,30,40]
>>> tuple2=tuple1
>>> tuple2
[20, 30, 40]
>>> tuple2[1]=10
>>> print(tuple2)
[20, 10, 40]
>>> print(tuple1)
[20, 10, 40]