Подтвердить что ты не робот

Python: изменение значения в кортеже

Я новичок в python, поэтому этот вопрос может быть немного базовым. У меня есть кортеж под названием values, который содержит следующее:

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

Я хочу изменить первое значение (т.е. 275) в этом кортеже, но я понимаю, что кортежи неизменяемы, поэтому values[0] = 200 не будет работать. Как я могу достичь этого?

4b9b3361

Ответ 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]