अजगर: एक टुपल में बदलते मूल्य


124

मैं अजगर के लिए नया हूं इसलिए यह सवाल थोड़ा बुनियादी हो सकता है। मेरे पास एक ट्यूपल है valuesजिसमें निम्नलिखित शामिल हैं:

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

मैं 275इस tuple में पहला मान (यानी ) बदलना चाहता हूं, लेकिन मैं समझता हूं कि tuples अपरिवर्तनीय है इसलिए values[0] = 200काम नहीं करेगा। इसे कैसे प्राप्त किया जा सकता है?


24
tuples अपरिवर्तनीय हैं , इसे प्राप्त करने के लिए आपको एक नया tuple बनाने की आवश्यकता है।
हंटर मैकमिलन

जवाबों:


178

पहले आपको यह पूछने की ज़रूरत है कि आप ऐसा क्यों करना चाहते हैं?

लेकिन यह संभव है:

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

लेकिन अगर आपको चीजों को बदलने की जरूरत पड़ती है, तो आप शायद इसे रखने से बेहतर हैं list


4
एक उपयोग मामला यह है कि यदि आप बड़ी संख्या में छोटे अनुक्रमों को संग्रहीत कर रहे हैं, जहां मान शायद ही कभी बदलते हैं लेकिन कुछ अवसरों पर वे चाहते हैं। एक छोटे लेकिन गैर-शून्य लंबाई अनुक्रम के लिए, टपल की मेमोरी खपत (एक तत्व के लिए 60-बाइट्स) बनाम सूची (104 बाइट्स) और एक फर्क पड़ता है। नामसूची के लिए एक अन्य उपयोग का मामला है क्योंकि नामसूची में मूल रूप से मौजूद नहीं है।
माइकल स्कॉट कटहबर्ट

81
"आप ऐसा क्यों करना चाहते हैं" प्रतिक्रियाएं मुझे StackOverflow पर पागल कर देती हैं। ऐसा मत मानिए कि मूल पोस्टर "चाहता" है। वास्तव में, यह नहीं मानना ​​बेहतर है कि मूल पोस्टर खरोंच से यह सब बना रहा है किसी भी बेहतर पता नहीं है। अधिक बार हम किसी अन्य मॉड्यूल या डेटा स्रोत से आउटपुट के साथ एक प्रारूप या प्रकार में काम कर रहे हैं जिसे हम नियंत्रित नहीं कर सकते हैं।
रतफॉकी

9
@rtphokie एक अपरिवर्तनीय कंटेनर (इसलिए "क्यों" एक बहुत ही वैध प्रश्न है) को अलग-अलग स्वरूपों की व्याख्या से अलग करना चाहता है, जिनमें से कुछ एक ट्यूपल हो सकते हैं। हालांकि :) निकाल लिए धन्यवाद
जॉन क्लेमेंट्स

7
यह एक सूची में फिर से आना और एक अस्थायी चर का उपयोग करने के लिए अनावश्यक और स्मृति अक्षम लगता है। आप बस एक ही नाम के साथ एक ट्यूपल में अनपैक कर सकते हैं और अपडेट को अनपैक करते समय जो कुछ भी अपडेट करने की आवश्यकता है।
ब्रायन स्पाइरिंग

5
@JonClements आप एक बहुत मूल्यवान बिंदु बनाते हैं कि ऐसा करना बुरा अभ्यास है। वह आपके उत्तर में होना चाहिए । हालांकि बयानबाजी के सवालों को अक्सर अनावश्यक रूप से अपमानजनक माना जाता है। इस तरह की जानकारी बेहतर रूप में संरचित है: "यह बुरा अभ्यास है क्योंकि ..." या यहां तक ​​कि "ध्यान से विचार करें यदि आपको वास्तव में इसकी आवश्यकता है, तो यह आमतौर पर डिजाइन में एक गलती का कारण
बनता है

74

आपकी समस्या के आधार पर टुकड़ा करने की क्रिया वास्तव में साफ समाधान हो सकती है:

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

यह आपको कई तत्वों को जोड़ने की अनुमति देता है या कुछ तत्वों को बदलने के लिए भी (विशेष रूप से यदि वे "पड़ोसी" हैं। उपरोक्त मामले में किसी सूची में कास्टिंग करना अधिक उपयुक्त और पठनीय है (भले ही स्लाइसिंग नोटेशन बहुत छोटा हो)।


24

खैर, जैसा कि ट्रूफ़ा ने पहले ही दिखाया है, मूल रूप से एक दिए गए इंडेक्स में टपल के तत्व को बदलने के दो तरीके हैं। या तो टपल को सूची में बदलें, तत्व को बदलें और वापस रूपांतरित करें, या संघनन द्वारा एक नया टपल का निर्माण करें।

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

तो, कौन सा तरीका बेहतर है, जो कि तेज है?

यह पता चला है कि छोटे ट्यूपल्स के लिए (पायथन 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

बहुत लंबे tuples के लिए, सूची रूपांतरण काफी बेहतर है!

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

इसलिए: यदि आपका टुपल छोटा है, तो स्लाइस और कंसीनेट करें। यदि यह लंबा है, तो सूची रूपांतरण करें!


1
@ ErikAronesty हमेशा नहीं। एक बार उपयोगी मामला एक वर्ग का विस्तार कर रहा है जिसे आप बदल नहीं सकते हैं और जिसके तरीके एक टपल लौटाते हैं जिसमें से आप पहले तत्व को बदलना चाहते हैं। वापसी (वैल,) + रेस [1:] res2 = सूची (रेस) की तुलना में स्पष्ट है; res2 [0] = वैल; वापसी टपल (रेस 2)
यूलर

9

यह एक लाइनर के साथ संभव है:

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

1
आप इसमें केवल तीसरे तत्व को कैसे बदलेंगे values?
sdbbs 12

2
यहां बताया गया है कि आप किसी भी तत्व को एक ट्यूपल में कैसे बदल सकते हैं -i = 2; values = (*values[:i], '300', *values[i+1:])
ब्रायन स्पाइरिंग

8

ऐसा नहीं है कि यह श्रेष्ठ है, लेकिन अगर किसी को उत्सुक है तो इसे एक पंक्ति में किया जा सकता है:

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

क्या इससे तेज है tuple = tuple(200 if i == 0 else _ for i, _ in enumerate(tuple))? (जेनरेटर कॉम्प्रिहेंशन क्यों नहीं?)
बेनामी

8

मेरा मानना ​​है कि यह तकनीकी रूप से प्रश्न का उत्तर देता है, लेकिन घर पर ऐसा न करें। फिलहाल, सभी उत्तरों में एक नया टपल बनाना शामिल है, लेकिन आप ctypesटुप-इन-मेमोरी को संशोधित करने के लिए उपयोग कर सकते हैं । 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

1
हमेशा सामान्य उत्तरों की तुलना में कुछ अलग जानना अच्छा होता है। चियर्स!
कार्तिके पलपु २

जो लोग C में कोड करना चाहते हैं, उन्हें शायद ऐसा ही करना चाहिए। इंटरप्रेटर को इस तरह हैक करना कि यहां विषय याद आ जाए। यह भी अविश्वसनीय है, क्योंकि cPython कार्यान्वयन विवरण चेतावनी के बिना किसी भी समय बदल सकता है और किसी भी कोड को तोड़ने की संभावना है जो टुप्लस मधुमक्खी पर निर्भर करता है। इसके अलावा, ट्यूलिप अजगर में सबसे हल्के संग्रह की वस्तुएं हैं, इसलिए नया बनाने में कोई समस्या नहीं है। यदि आपको किसी संग्रह को बार-बार संशोधित करने की आवश्यकता है, तो इसके बजाय एक सूची का उपयोग करें।
बछसौ

1
आप उस मूल्य को संदर्भ संख्या में कमी करना भूल गए हैं जिसे आप छोड़ रहे हैं। यह रिसाव का कारण होगा।
wizzwizz4

6

जैसा कि हंटर मैकमिलन ने टिप्पणियों में लिखा है, ट्यूपल्स अपरिवर्तनीय हैं, इसे प्राप्त करने के लिए आपको एक नया टपल बनाने की आवश्यकता है। उदाहरण के लिए:

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

3

संपादित करें: यह अभी तक डुप्लिकेट प्रविष्टियों के साथ tuples पर काम नहीं करता है !!

पूया के विचार पर आधारित :

यदि आप अक्सर ऐसा करने की योजना बना रहे हैं (जो आपको तब से नहीं करना चाहिए जब टुपल्स एक कारण से अयोग्य हैं) तो आपको कुछ ऐसा करना चाहिए:

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

3

मुट्ठी, अपने आप से पूछें कि आप अपने को क्यों बदलना चाहते हैं tupleएक कारण है कि पाइथन में स्ट्रिंग्स और ट्यूपल अपरिवर्तनीय हैं , यदि आप अपने को बदलना चाहते हैं, tupleतो यह संभवतः एक होना चाहिए list

दूसरा, यदि आप अभी भी अपने ट्यूल को म्यूट करना चाहते हैं तो आप अपने tupleको listतब कन्वर्ट कर सकते हैं, इसे वापस कन्वर्ट कर सकते हैं, और नए टपल को उसी वेरिएबल में पुनः असाइन कर सकते हैं। यह बहुत अच्छा है अगर आप केवल एक बार अपने टपल को म्यूट करने जा रहे हैं । अन्यथा, मैं व्यक्तिगत रूप से सोचता हूं कि यह प्रतिवाद है। क्योंकि यह अनिवार्य रूप से एक नया tuple बना रहा है और हर बार यदि आप tuple को बदलना चाहते हैं तो आपको रूपांतरण करना होगा। इसके अलावा, यदि आप कोड को पढ़ते हैं तो यह सोचना भ्रामक होगा कि सिर्फ ए ही क्यों नहीं list? लेकिन यह अच्छा है क्योंकि इसके लिए किसी पुस्तकालय की आवश्यकता नहीं है।

मैं उत्परिवर्तन 0.2mutabletuple(typename, field_names, default=MtNoDefault) से उपयोग करने का सुझाव देता हूं । मुझे व्यक्तिगत रूप से लगता है कि यह तरीका अधिक सहज और पठनीय है। कोड को पढ़ने वाले व्यक्तिगत को पता होगा कि लेखक भविष्य में इस टपल को म्यूट करने का इरादा रखता है। ऊपर की रूपांतरण विधि की तुलना में नकारात्मक पक्ष यह है कि इसके लिए आपको अतिरिक्त पाई फ़ाइल आयात करने की आवश्यकता होती है।list

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


2

जॉन के विचार और प्रिय 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")

यह आपके सभी पुराने मूल्यों में परिवर्तन करता है


यह काफी असहज होगा (एक बेहतर शब्द की कमी के लिए) यदि आप कई मूल्यों को बदलना चाहते थे, लेकिन फिर से, आप पहले स्थान पर एक
ट्यूल

डी: @Trufa हाँ, मैं यह लिखने के लिए कोशिश कर रहा हूँ
Pooya

विधि का नाम rev_tuple_by_index गलत है और भ्रम का कारण है।
msw

1

आप नहीं कर सकते। यदि आप इसे बदलना चाहते हैं, तो आपको टुप के बजाय एक सूची का उपयोग करने की आवश्यकता है।

ध्यान दें कि आप इसके बजाय एक नया टपल बना सकते हैं जिसका नया तत्व इसके पहले तत्व के रूप में है।


0

मैंने tuples को संपादित करने का सबसे अच्छा तरीका पाया है कि पिछले संस्करण का उपयोग आधार के रूप में 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)

tuple = tuple के माध्यम से iterate, प्रत्येक आइटम को आवश्यकतानुसार बदल दें

यह अवधारणा है।


0

मुझे खेल में देर हो गई है लेकिन मुझे लगता है कि सबसे सरल , संसाधन-मित्र और सबसे तेज़ तरीका (स्थिति पर निर्भर करता है) , टपल को खुद से लिखना है। चूंकि यह सूची और चर निर्माण की आवश्यकता को हटा देगा और इसे एक पंक्ति में संग्रहीत किया जाएगा।

new = 24
t = (1, 2, 3)
t = (t[0],t[1],new)

>>> (1, 2, 24)

लेकिन: यह केवल छोटे tuples के लिए ही उपयोगी है और आपको एक निश्चित tuple मान तक सीमित करता है, फिर भी, यह वैसे भी ज्यादातर समय tuples के लिए होता है।

तो इस विशेष मामले में यह इस तरह दिखेगा:

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

यह केवल तभी काम करता है जब यह ज्ञात लंबाई के साथ एक स्थिर ट्यूपल हो। कोड बहुत जल्दी या बाद में असफल होने की संभावना है क्योंकि इसका बहुत विशिष्ट ...
patroqueeet

हां - @patroqueeet, इसलिए मैंने स्पष्ट रूप से इस दृष्टिकोण के डाउनसाइड्स के बारे में कहा, लेकिन बाद में: ...-। कृपया अपने
पतन

1
हे, फिर से विचार किया और बटन पर क्लिक किया। लेकिन वोट अब SO: /
patroqueeet

0

tldr; "वर्कअराउंड" एक नया टपल ऑब्जेक्ट बना रहा है, वास्तव में मूल को संशोधित नहीं कर रहा है

जबकि यह एक बहुत पुराना सवाल है, किसी ने मुझे इस पाइथन म्यूटिंग ट्यूपल्स पागलपन के बारे में बताया। जिसे मैं बहुत आश्चर्यचकित / साज़िश कर रहा था, और कुछ गुगली कर रहा था, मैं यहाँ उतरा (और इसी तरह के अन्य नमूने ऑनलाइन)

मैंने अपने सिद्धांत को साबित करने के लिए कुछ परीक्षण किए

नोट रेफ़रेंशियल ==इक्वैलिटी करते समय समता को महत्व देता है is(obj b के समान उदाहरण है)

a = ("apple", "canana", "cherry")
b = tuple(["apple", "canana", "cherry"])
c = a

print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))

d = list(a)
d[1] = "kiwi"
a = tuple(d)

print("a: " + str(a))
print("b: " + str(b))
print("c: " + str(c))
print("a == b :: %s" % (a==b))
print("b == c :: %s" % (b==c))
print("a == c :: %s" % (a==c))
print("a is b :: %s" % (a is b))
print("b is c :: %s" % (b is c))
print("a is c :: %s" % (a is c))

पैदावार:

a: ('apple', 'canana', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: True
b == c :: True
a == c :: True
a is b :: False
b is c :: False
a is c :: True
a: ('apple', 'kiwi', 'cherry')
b: ('apple', 'canana', 'cherry')
c: ('apple', 'canana', 'cherry')
a == b :: False
b == c :: True
a == c :: False
a is b :: False
b is c :: False
a is c :: False

0

आप टपल में आइटम को संशोधित नहीं कर सकते हैं, लेकिन आप टुपल्स में उत्परिवर्तनीय वस्तुओं के गुणों को संशोधित कर सकते हैं (उदाहरण के लिए यदि वे ऑब्जेक्ट सूची या वास्तविक वर्ग ऑब्जेक्ट हैं)

उदाहरण के लिए

my_list = [1,2]
tuple_of_lists = (my_list,'hello')
print(tuple_of_lists) # ([1, 2], 'hello')
my_list[0] = 0
print(tuple_of_lists) # ([0, 2], 'hello')

-2

इसे मैने किया है:

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

और बदलने के लिए, बस करो

list[0]=6

और आप एक नलिका बदल सकते हैं: डी

यहाँ इसे 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
tuple एक सूची है, tuple नहीं। x = (y)कुछ भी नहीं है लेकिन y को x असाइन करता है।
m4tx

2
चर के रूप में "tuple" और "list" नाम का उपयोग करके, आप बाद में tuple और सूची प्रकारों की तुलना करना कठिन बना देंगे।
माइकल स्कॉट कटहबर्ट

-4

आप संदर्भ द्वारा प्रतिलिपि का उपयोग करके टुपल के मूल्य को बदल सकते हैं

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

>>> tuple2=tuple1

>>> tuple2
    [20, 30, 40]

>>> tuple2[1]=10

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

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

1
केवल यह कि ये सूचियाँ हैं, टुपल्स नहीं, जिन्हें आप किसी भी तरह बदल सकते हैं, दूसरा संदर्भ दिया गया है या नहीं।
बछसौ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.