Python: changer la valeur d'un tuple

je suis nouveau en python donc cette question pourrait être un peu basique. J'ai un tuple appelé values qui contient ce qui suit:

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

je veux changer la première valeur (i.e., 275 ) dans ce tuple mais je comprends que tuples sont immuables de sorte que values[0] = 200 ne fonctionnera pas. Comment puis-je y parvenir?

69
demandé sur Dawood 2012-07-12 22:27:42

14 réponses

vous devez d'Abord demander, pourquoi vous voulez le faire?

mais c'est possible via:

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

mais si vous devez changer les choses, vous êtes probablement mieux de le garder comme un list

104
répondu Jon Clements 2012-07-12 18:29:29

selon votre problème le tranchage peut être une solution très soignée:

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

cela vous permet d'ajouter plusieurs éléments ou aussi de remplacer quelques éléments (surtout s'ils sont"voisins"). Dans le cas ci-dessus casting à une liste est probablement plus approprié et lisible (même si la notation de tranchage est beaucoup plus courte).

42
répondu Dave Halter 2014-03-27 00:53:59

Eh bien, comme Trufa L'a déjà montré, il y a essentiellement deux façons de remplacer l'élément d'un tuple à un indice donné. Soit convertissez le tuple en liste, remplacez l'élément et convertissez en arrière, ou construisez un nouveau tuple par concaténation.

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:]
   ...:

Alors, quelle méthode est la meilleure, c'est plus rapide?

il s'avère que pour les courts tuples (sur Python 3.3), la concaténation est en fait plus rapide!

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

pourtant si nous regardez plus long tuples, la conversion de liste est la voie à suivre:

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

pour les tuples Très longs, la conversion de liste est nettement meilleure!

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

en outre, la performance de la méthode de concaténation dépend de l'indice auquel nous remplaçons l'élément. Pour la méthode list, l'index n'est pas pertinent.

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

ainsi: si votre tuple est court, trancher et concaténer. Si c'est long, faites la conversion de liste!

14
répondu sjakobi 2013-11-23 10:14:10

comme Hunter McMillen l'a écrit dans les commentaires, les tuples sont immuables, vous devez créer un nouveau tuple afin d'atteindre cet objectif. Par exemple:

>>> 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')
4
répondu Vikram S 2016-06-13 13:43:25

non pas que ce soit supérieur, mais si quelqu'un est curieux il peut être fait sur une ligne avec:

tuple = tuple([200 if i == 0 else _ for i, _ in enumerate(tuple)])
3
répondu bphi 2016-11-11 19:28:42

EDIT: cela ne fonctionne pas encore sur les tuples avec des entrées en double!!

Basé sur Pooya l'idée de :

si vous prévoyez de le faire souvent (ce que vous ne devriez pas puisque les tuples sont inmutables pour une raison) vous devriez faire quelque chose comme ceci:

def modTupByIndex(tup, index, ins):
    return tuple(tup[0:index]) + (ins,) + tuple(tup[index+1:])

print modTupByIndex((1,2,3),2,"a")

Ou basé sur de Jon idée :

def modTupByIndex(tup, index, ins):
    lst = list(tup)
    lst[index] = ins
    return tuple(lst)

print modTupByIndex((1,2,3),1,"a")
2
répondu Trufa 2017-05-23 12:10:28

basé sur Jon l'Idée et cher 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")

il modifie toutes vos anciennes valeurs occurrences

2
répondu Pooya 2017-05-23 11:47:19

Frist, demandez-vous pourquoi vous voulez muter votre tuple . il y a une raison pour laquelle cordes et tuples sont immuables en Ptyhon , si vous voulez muter votre tuple alors il devrait probablement être un list à la place.

deuxièmement, si vous souhaitez encore muter votre tuple, vous pouvez convertir votre tuple en list puis le convertir en arrière, et réassigner le nouveau tuple à la même variable. C'est grand si vous allez muter votre tuple qu'une fois . Autrement, je pense personnellement que c'est contre-intuitif. Parce que C'est essentiellement la création d'un nouveau tuple et à chaque fois si vous souhaitez muter le tuple vous auriez à effectuer la conversion. Aussi, Si vous lisez le code, il serait trompeur de penser, pourquoi ne pas simplement créer un list ? Mais c'est bien parce qu'il n'a pas besoin de bibliothèque.

je suggère d'utiliser mutabletuple(typename, field_names, default=MtNoDefault) de mutabletuple 0.2 . Je pense personnellement que cette façon est un plus intuitif et lisible. la lecture personnelle du code saurait que l'écrivain a l'intention de muter ce tuple à l'avenir. L'inconvénient par rapport à la méthode de conversion list ci-dessus est que cela vous oblige à importer le fichier PY supplémentaire.

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 : N'essayez pas de muter tuple . si vous le faites et qu'il s'agit d'une opération unique, convertissez tuple pour lister, muter , transformer list en un nouveau tuple , et réattribuez à la variable contenant l'ancienne tuple . Si désire tuple et en quelque sorte veulent éviter list et veulent muter plus d'une fois alors créer mutabletuple .

1
répondu OLIVER.KOO 2017-08-15 20:20:28

je crois que cela répond techniquement à la question, mais ne faites pas cela à la maison. Pour le moment, toutes les réponses impliquent la création d'un nouveau tuple, mais vous pouvez utiliser ctypes pour modifier un tuple en mémoire. En se basant sur divers détails d'implémentation de CPython sur un système 64 bits, une façon de faire ceci est la suivante:

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
1
répondu fuglede 2018-02-05 20:43:50

vous ne pouvez pas. Si vous voulez le changer, vous devez utiliser une liste au lieu d'un tuple.

notez que vous pouvez à la place faire un nouveau tuple qui a la nouvelle valeur comme premier élément.

0
répondu BrenBarn 2012-07-12 18:29:58

j'ai trouvé que la meilleure façon d'éditer tuples est de recréer le tuple en utilisant la version précédente comme base.

Voici un exemple que j'ai utilisé pour faire une version plus légère de couleur (je l'avais déjà ouvert à l'époque):

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

ce qu'il fait, c'est qu'il passe à travers la "couleur" de tuple et lit chaque article, lui fait quelque chose, et finalement l'ajoute à la nouvelle tuple.

Donc, ce que vous voulez serait quelque chose comme:

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

values  = (tuple(for i in values: if i = 0: i = 200 else i = values[i])

ce spécifique ne fonctionne pas, mais le concept est ce dont vous avez besoin.

tuple = (0, 1, 2)

tuple = itérer n-uplet, de modifier chaque élément en tant que de besoin

c'est le concept.

0
répondu Aedus 2017-08-15 19:12:15

vous pouvez changer la valeur de tuple en utilisant 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]
0
répondu Rohit 2018-10-02 15:05:48

il s'agit d'une doublure simple en Python idoimatique:

values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])
0
répondu Brian Spiering 2018-10-05 03:34:26

j'ai fait ceci:

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

et pour changer, il suffit de faire

list[0]=6

et u peut changer un tuple: d

ici il est copié exactement de 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]
-2
répondu MC_Creep3r 2014-11-01 21:17:26