Python: изменение значения в кортеже
Я новичок в python, поэтому этот вопрос может быть немного базовым. У меня есть кортеж под названием values
, который содержит следующее:
('275', '54000', '0.0', '5000.0', '0.0')
Я хочу изменить первое значение (т.е. 275
) в этом кортеже, но я понимаю, что кортежи неизменяемы, поэтому values[0] = 200
не будет работать. Как я могу достичь этого?
Ответы
Ответ 1
Сначала вам нужно спросить, почему вы хотите это сделать?
Но это возможно через:
t = ('275', '54000', '0.0', '5000.0', '0.0')
lst = list(t)
lst[0] = '300'
t = tuple(lst)
Но если вам нужно будет что-то менять, вам, вероятно, лучше держать его как list
Ответ 2
В зависимости от вашей проблемы нарезка может быть действительно опрятным решением:
>>> 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)
Это позволяет добавлять несколько элементов или заменять несколько элементов (особенно, если они являются "соседями". В приведенном выше примере листинг в списке, вероятно, более уместен и читабельен (хотя нотация среза намного короче).
Ответ 3
Ну, как уже показало 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
Итак: если ваш кортеж короток, нарежьте и соедините.
Если он длинный, выполните преобразование списка!
Ответ 4
Как писал Хантер Макмиллен в комментариях, кортежи неизменяемы, для этого нужно создать новый кортеж. Например:
>>> 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')
Ответ 5
Не то, чтобы это было лучше, но если кому-то интересно, это можно сделать в одной строке:
tuple = tuple([200 if i == 0 else _ for i, _ in enumerate(tuple)])
Ответ 6
Я считаю, что это технически отвечает на вопрос, но не делайте этого дома. На данный момент все ответы включают создание нового кортежа, но вы можете использовать ctypes
для изменения кортежа в памяти. Опираясь на различные детали реализации CPython в 64-битной системе, можно сделать следующее:
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
Ответ 7
Это простой однострочный текст, использующий Python: idoimatic:
values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])
Ответ 8
на основе 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")
он изменяет все ваши старые значения вхождения
Ответ 9
EDIT: это не работает с кортежами с повторяющимися записями.
На основе идеи 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")
Ответ 10
Фрист, спросите себя, почему вы хотите изменить ваш 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
и переназначить обратно в переменную, содержащую старый tuple
. Если вы хотите tuple
и как-то хотите избежать list
и хотите мутировать более одного раза, создайте mutabletuple
.
Ответ 11
Вы не можете. Если вы хотите изменить его, вам нужно использовать список вместо кортежа.
Обратите внимание, что вместо этого вы можете создать новый кортеж с новым значением в качестве его первого элемента.
Ответ 12
Я нашел, что лучший способ редактировать кортежи - воссоздать кортеж, используя предыдущую версию в качестве базы.
Вот пример, который я использовал для создания более светлой версии цвета (у меня он был открыт уже в то время):
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 = итерация через кортеж, изменение каждого элемента по мере необходимости
что понятие.
Ответ 13
Я опаздываю к игре, но думаю, что самый простой, дружественный к ресурсам и самый быстрый способ (в зависимости от ситуации),
это перезаписать сам кортеж. Поскольку это устранит необходимость в списке & создание переменной и архивируется в одну строку.
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')
Ответ 14
Я сделал это:
list = [1,2,3,4,5]
tuple = (list)
и изменить, просто сделайте
list[0]=6
и u может изменить кортеж: 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]
Ответ 15
Вы можете изменить значение кортежа с помощью копирования по ссылке
>>> tuple1=[20,30,40]
>>> tuple2=tuple1
>>> tuple2
[20, 30, 40]
>>> tuple2[1]=10
>>> print(tuple2)
[20, 10, 40]
>>> print(tuple1)
[20, 10, 40]