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?
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
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).
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!
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')
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)])
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")
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
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
.
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
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.
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.
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]
il s'agit d'une doublure simple en Python idoimatique:
values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])
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]