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



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



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


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

889   14  

14 ответов:

сначала вы должны спросить, почему вы хотите это сделать?

но это возможно через:

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

но если вам нужно будет что-то изменить, вам, вероятно, лучше сохранить его как list

в зависимости от вашей проблемы нарезка может быть действительно аккуратным решением:

>>> 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)

Это позволяет добавить несколько элементов или же заменить несколько элементов (особенно, если они являются "соседями". В приведенном выше случае приведение к списку, вероятно, более уместно и читаемо (хотя нотация нарезки намного короче).

Ну, как уже показал 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

кроме того, производительность метода конкатенации зависит от индекса, при котором мы заменяем элемент. Для метода list индекс не имеет значения.

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

Итак: если ваш кортеж короткий, нарезать и объединить. Если это долго, сделайте преобразование списка!

Как написал Хантер Макмиллен в комментариях, кортежи неизменны, вам нужно создать новый кортеж, чтобы достичь этого. Например:

>>> 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')

Не то, чтобы это превосходно, но если кому-то интересно, это можно сделать в одной строке с:

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

EDIT: это еще не работает на кортежах с повторяющимися записями!!

на основе Pooya идея:

Если вы планируете делать это часто (что вы не должны, так как кортежи inmutable по какой-то причине), вы должны сделать что-то вроде этого:

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")

на основе Йон идея и дорогой 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")

Он изменяет все ваши старые значения вхождения

Фрист, спроси себя, Почему ты хочешь мутировать свой tuple. есть причина, почему строки и кортежи являются неизменяемыми в Ptyhon, если вы хотите видоизменить свой tuple тогда это, вероятно, должно быть .

во-вторых, если вы все еще хотите мутировать свой кортеж, то вы можете конвертировать ваш 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.

Я считаю, что это технически отвечает на вопрос, но не делайте это дома. На данный момент все ответы связаны с созданием нового кортежа, но вы можете использовать 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

вы не можете. Если вы хотите изменить его, вы должны использовать список, а не Кортеж.

обратите внимание, что вместо этого вы можете создать новый Кортеж, который имеет новое значение в качестве первого элемента.

Я нашел лучший способ редактирования кортежей, чтобы воссоздать кортеж, используя предыдущую версию в качестве базы.

вот пример, который я использовал для создания более светлой версии цвета (я уже открыл его в то время):

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)

кортеж = итерации через кортеж, изменить каждый элемент по мере необходимости

это понятие.

вы можете изменить значение кортежа, используя copy by reference

>>> tuple1=[20,30,40]

>>> tuple2=tuple1

>>> tuple2
    [20, 30, 40]

>>> tuple2[1]=10

>>> print(tuple2)
    [20, 10, 40]

>>> print(tuple1)
    [20, 10, 40]

Это скачайте стоковую фотографию Bahia один-лайнер, используя idoimatic питон:

values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])

Я сделал так:

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]

Comments

    Ничего не найдено.