私はpythonが初めてなので、この質問は少し基本的なものかもしれません。次を含むvalues
というタプルがあります。
('275', '54000', '0.0', '5000.0', '0.0')
このタプルの最初の値(つまり、275
)を変更したいのですが、タプルは不変であるため、values[0] = 200
は機能しません。どうすればこれを達成できますか?
最初に尋ねる必要があります、なぜあなたはこれをしたいのですか?
しかし、それは可能です:
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がすでに示したように、特定のインデックスでTupleの要素を置き換えるには、基本的に2つの方法があります。タプルをリストに変換するか、要素を置き換えて元に戻すか、連結によって新しいタプルを作成します。
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
つまり、タプルが短い場合は、スライスして連結します。長い場合は、リスト変換を行います!
Hunter McMillenがコメントで書いたように、タプルは不変です。これを実現するには、新しいタプルを作成する必要があります。例えば:
>>> 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')
これは、慣用的なPythonを使用した簡単なワンライナーです。
values = ('275', '54000', '0.0', '5000.0', '0.0')
values = ('300', *values[1:])
技術的にはこれで質問に答えられると思いますが、自宅ではそうしないでください。現時点では、すべての回答には新しいタプルの作成が含まれますが、ctypes
を使用してメモリ内のタプルを変更できます。 64ビットシステムでのCPythonのさまざまな実装の詳細に依存して、これを行う1つの方法は次のとおりです。
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行で実行できます。
Tuple = Tuple([200 if i == 0 else _ for i, _ in enumerate(Tuple)])
最初に、Tuple
を変更する理由を自問してください。Ptyhonでは文字列とタプルが不変である理由があります。Tuple
を変更したい場合は、おそらくlist
である必要があります。
2番目に、まだタプルを変更したい場合は、Tuple
をlist
に変換してから変換し直し、新しいタプルを同じ変数に再割り当てできます。これは素晴らしいですタプルを1回だけ変更する場合。そうでなければ、個人的には直感に反すると思います。本質的に新しいタプルを作成しているため、タプルを変更する場合は毎回変換を実行する必要があります。また、コードを読んだ場合、単にlist
を作成しないのはなぜかと考えると混乱しますか?しかし、ライブラリを必要としないため、素晴らしいです。
mutabletuple 0.2 からmutabletuple(typename, field_names, default=MtNoDefault)
を使用することをお勧めします。個人的には、この方法はmore直感的およびreadable.であると思います。このタプルを将来的に変更するために。上記の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
を作成します。
編集:これはまだ重複エントリを持つタプルでは動作しません!
Pooyaのアイデア に基づく:
これを頻繁に行うことを計画している場合(タプルは理由により不変なので、そうすべきではありません)、次のようなことをする必要があります。
def modTupByIndex(tup, index, ins):
return Tuple(tup[0:index]) + (ins,) + Tuple(tup[index+1:])
print modTupByIndex((1,2,3),2,"a")
または Jonのアイデア に基づいて:
def modTupByIndex(tup, index, ins):
lst = list(tup)
lst[index] = ins
return Tuple(lst)
print modTupByIndex((1,2,3),1,"a")
私はゲームに遅れていますが、(最も単純な、リソースにやさしい、最速の方法(状況に応じて)、タプル自体を上書きすることです。これにより、リストと変数を作成する必要がなくなり、1行でアーカイブされます。
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')
できません。変更したい場合は、タプルの代わりにリストを使用する必要があります。
代わりに、新しい値を最初の要素として持つ新しいTupleを作成できることに注意してください。
タプルを編集する最良の方法は、以前のバージョンをベースとしてタプルを再作成することです。
これは、明るいバージョンの色を作成するために使用した例です(その時点で既に開いていました)。
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)
タプル=タプルを反復処理し、必要に応じて各項目を変更します
それがコンセプトです。