पायथन तार अपरिवर्तनीय नहीं हैं? तो फिर A + "+ b काम क्यों करता है?


109

मेरी समझ यह थी कि पायथन के तार अपरिवर्तनीय हैं।

मैंने निम्नलिखित कोड आज़माया:

a = "Dog"
b = "eats"
c = "treats"

print a, b, c
# Dog eats treats

print a + " " + b + " " + c
# Dog eats treats

print a
# Dog

a = a + " " + b + " " + c
print a
# Dog eats treats
# !!!

क्या अजगर को काम नहीं रोकना चाहिए था? मुझे शायद कुछ याद आ रहा है।

कोई उपाय?


55
स्ट्रिंग स्वयं अपरिवर्तनीय है लेकिन लेबल बदल सकता है।
मिच

6
किसी मौजूदा वैरिएबल को नया मान देना पूरी तरह से मान्य है। पायथन में स्थिरांक नहीं होते हैं। यह डेटा प्रकार उत्परिवर्तन से स्वतंत्र है।
फेलिक्स क्लिंग

14
आप id()फ़ंक्शन पर एक नज़र डालना चाहते हैं । aअसाइनमेंट से पहले और बाद में एक अलग आईडी होगी, यह दर्शाता है कि यह अलग-अलग ऑब्जेक्ट्स की ओर इशारा कर रहा है। इसी तरह कोड के साथ b = aआप पाएंगे कि aऔर bएक ही आईडी होगी, यह दर्शाता है कि वे एक ही वस्तु को संदर्भित कर रहे हैं।
DRH


डेलनान से लिंक बिल्कुल वही है जिसका मैं उल्लेख कर रहा था।
मिच

जवाबों:


180

पहले aस्ट्रिंग "डॉग" की ओर इशारा किया। फिर आपने aएक नए स्ट्रिंग "डॉग ईट्स ट्रीट्स" को इंगित करने के लिए चर को बदल दिया । आपने वास्तव में स्ट्रिंग "डॉग" को म्यूट नहीं किया था। स्ट्रिंग्स अपरिवर्तनीय हैं, चर जो चाहे उन्हें इंगित कर सकते हैं।


34
यह x = 'abc' जैसी किसी चीज़ को आज़माने के लिए और भी ठोस है; x [1] = पायथन उत्तर में 'x'
xpmatteo

1
यदि आप इंटर्न को थोड़ा और समझना चाहते हैं, तो मेरा जवाब देखें। stackoverflow.com/a/40702094/117471
ब्रूनो ब्रोंस्की

53

स्ट्रिंग ऑब्जेक्ट स्वयं अपरिवर्तनीय हैं।

वैरिएबल, aजो स्ट्रिंग को इंगित करता है, परस्पर परिवर्तनशील है।

विचार करें:

a = "Foo"
# a now points to "Foo"
b = a
# b points to the same "Foo" that a points to
a = a + a
# a points to the new string "FooFoo", but b still points to the old "Foo"

print a
print b
# Outputs:

# FooFoo
# Foo

# Observe that b hasn't changed, even though a has.

@ajon सूचियों के साथ एक ही तरह के ऑपरेशन की कोशिश करते हैं (जो कि परस्पर भिन्न होते हैं) a.append (3) अंतर को देखने के लिए a = a + "Foo" से मेल खाती है
jimifiki

1
@ जिमीकिकी जैसी a.append(3) नहीं है a = a + 3। यह भी नहीं है a += 3(inplace अलावा इसके बराबर है .extend, नहीं .append)।

@ डायलेन और इसलिए, क्या? यह दिखाने के लिए कि तार और सूचियाँ अलग-अलग व्यवहार करती हैं आप मान सकते हैं कि a = a + "Foo" a.append (कुछ) के समान है। किसी भी मामले में यह समान नहीं है। जाहिर है। क्या आप a.append (कुछ) के बजाय a.extend ([कुछ]) पढ़ रहे थे? मैं इस संदर्भ में उस बड़े अंतर को नहीं देखता। लेकिन शायद मुझे कुछ याद आ रहा है।
थ्रथ

@ जिमीफिकी: आप किस बारे में बात कर रहे हैं? +सूचियों और तारों के लिए समान व्यवहार करता है - यह एक नई प्रति बनाता है और किसी भी ऑपरेंड को परिवर्तित नहीं करता है।

6
इस सब से दूर ले जाने के लिए वास्तव में महत्वपूर्ण बिंदु यह है कि स्ट्रिंग्स का कोई append फ़ंक्शन
लिली चुंग

46

चर "ऑब्जेक्ट" कुत्ते की ओर इशारा कर रहा है। पायथन में एक टैग के रूप में चर के बारे में सोचना सबसे अच्छा है। आप टैग को विभिन्न ऑब्जेक्ट्स में ले जा सकते हैं, जो आपने तब बदला था जब आपने इसे बदल दिया a = "dog"था a = "dog eats treats"

हालाँकि, अपरिवर्तनीयता ऑब्जेक्ट को संदर्भित करती है, टैग को नहीं।


आप की कोशिश की तो a[1] = 'z'बनाने के लिए "dog"में "dzg", आपको त्रुटि मिलेगा:

TypeError: 'str' object does not support item assignment" 

क्योंकि तार आइटम असाइनमेंट का समर्थन नहीं करते हैं, इस प्रकार वे अपरिवर्तनीय हैं।


19

कुछ तभी परिवर्तनशील होता है जब हम मेमोरी लोकेशन में मौजूद वैल्यूज़ को मेमोरी लोकेशन को बदले बिना बदल सकते हैं।

चाल है: यदि आप पाते हैं कि परिवर्तन से पहले और बाद में स्मृति स्थान समान हैं, तो यह परिवर्तनशील है।

उदाहरण के लिए, सूची परिवर्तनशील है। कैसे?

>> a = ['hello']
>> id(a)
139767295067632

# Now let's modify
#1
>> a[0] = "hello new"
>> a
['hello new']
Now that we have changed "a", let's see the location of a
>> id(a)
139767295067632
so it is the same as before. So we mutated a. So list is mutable.

एक स्ट्रिंग अपरिवर्तनीय है। हम इसे कैसे साबित करेंगे?

> a = "hello"
> a[0]
'h'
# Now let's modify it
> a[0] = 'n'
----------------------------------------------------------------------

हमें मिला

TypeError: 'str' ऑब्जेक्ट आइटम असाइनमेंट का समर्थन नहीं करता है

इसलिए हम स्ट्रिंग को बदलने में विफल रहे। इसका मतलब है कि एक स्ट्रिंग अपरिवर्तनीय है।

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

>> a = "hello"
>> id(a)
139767308749440
>> a ="world"
>> id(a)
139767293625808

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


11

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


8

विचार करें:

>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='qwer'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x109198490>

ध्यान दें कि जब मैंने चर में दो बार समान मान संग्रहीत किया तो हेक्स मेमोरी लोकेशन नहीं बदला। जब मैंने एक अलग मूल्य संग्रहीत किया तो यह बदल गया। स्ट्रिंग अपरिवर्तनीय है। जीलोट्री के कारण नहीं, बल्कि इसलिए कि आप स्मृति में एक नई वस्तु बनाने के प्रदर्शन के दंड का भुगतान करते हैं। चर aसिर्फ उस स्मृति पते की ओर इशारा करते हुए एक लेबल है। किसी भी बात की ओर इशारा किया जा सकता है।


7

a = a + " " + b + " " + cसंकेत के आधार पर बयान को तोड़ा जा सकता है।

a + " "कहते हैं कि मुझे क्या संकेत देना चाहिए a, जिसे बदला नहीं जा सकता है, और " "मेरे वर्तमान कार्य सेट में जोड़ें ।

स्मृति:

working_set = "Dog "
a = "Dog" 
b = "eats"
c = "treats"

+ bकहते हैं कि मुझे कौन से bबिंदु हैं, जिन्हें बदला नहीं जा सकता है, और इसे वर्तमान कामकाजी सेट में जोड़ें।

स्मृति:

working_set = "Dog eats"
a = "Dog" 
b = "eats"
c = "treats"

+ " " + c" "वर्तमान सेट में जोड़ें । फिर मुझे कौन से cबिंदु दें, जिन्हें बदला नहीं जा सकता है, और इसे वर्तमान कामकाजी सेट में जोड़ें। स्मृति:

working_set = "Dog eats treats"
a = "Dog" 
b = "eats"
c = "treats"

अंत में, a =कहता है कि मेरे पॉइंटर को परिणामी सेट की ओर इंगित करें।

स्मृति:

a = "Dog eats treats"
b = "eats"
c = "treats"

"Dog"को पुनः प्राप्त किया जाता है, क्योंकि कोई और संकेत इसे स्मृति से नहीं जोड़ते हैं। हमने कभी भी मेमोरी सेक्शन में बदलाव नहीं किया "Dog"है, जो कि अपरिवर्तनीय है। हालाँकि, हम उस लेबल को बदल सकते हैं, यदि कोई हो, तो स्मृति के उस भाग को इंगित करें।


6
l = [1,2,3]
print id(l)
l.append(4)
print id(l) #object l is the same

a = "dog"
print id(a)
a = "cat"
print id(a) #object a is a new object, previous one is deleted

5

डेटा और उस लेबल के बीच एक अंतर है जो इसके साथ जुड़ा हुआ है। उदाहरण के लिए जब आप करते हैं

a = "dog"

डेटा "dog"बनाया और लेबल के तहत रखा गया है a। लेबल बदल सकता है लेकिन मेमोरी में जो है वह नहीं होगा। आपके द्वारा करने के बाद "dog"भी डेटा मेमोरी में मौजूद रहेगा (जब तक कि कचरा संग्रहकर्ता उसे हटा नहीं देता)

a = "cat"

आपके प्रोग्राम में aअब ^ ^ की ओर इशारा करता है, "cat"लेकिन स्ट्रिंग "dog"परिवर्तित नहीं हुई है।


3

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


2

चर वे चाहते हैं कि कहीं भी इंगित कर सकते हैं .. यदि आप निम्न कार्य करते हैं तो एक त्रुटि होगी:

a = "dog"
print a                   #dog
a[1] = "g"                #ERROR!!!!!! STRINGS ARE IMMUTABLE

2

अजगर स्ट्रिंग ऑब्जेक्ट अपरिवर्तनीय हैं। उदाहरण:

>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'

इस उदाहरण में हम देख सकते हैं कि जब हम इसमें अलग-अलग मूल्य देते हैं तो यह संशोधित नहीं होता है। एक नई वस्तु बनाई जाती है।
और इसे संशोधित नहीं किया जा सकता है। उदाहरण:

  >>> a[0] = 'c'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    **TypeError**: 'str' object does not support item assignment

एक त्रुटि होती है।


2

'परस्पर' का अर्थ है कि हम स्ट्रिंग की सामग्री को बदल सकते हैं, 'अपरिवर्तनीय' का अर्थ है कि हम एक अतिरिक्त स्ट्रिंग नहीं जोड़ सकते।

फोटो प्रूफ के लिए क्लिक करें


1

>>> a = 'dogs'

>>> a.replace('dogs', 'dogs eat treats')

'dogs eat treats'

>>> print a

'dogs'

अपरिवर्तनीय, है ना ?!

चर परिवर्तन भाग पर पहले ही चर्चा की जा चुकी है।


1
यह अजगर स्ट्रिंग्स की उत्परिवर्तन को साबित या बाधित नहीं कर रहा है, बस यह replace()विधि एक नया स्ट्रिंग लौटाती है।
ब्रेंट हैनिक

1

अपने उदाहरण के अलावा इस पर विचार करें

 a = "Dog"
 b = "eats"
 c = "treats"
 print (a,b,c)
 #Dog eats treats
 d = a + " " + b + " " + c
 print (a)
 #Dog
 print (d)
 #Dog eats treats

एक ब्लॉग में मुझे मिले अधिक सटीक स्पष्टीकरणों में से एक है:

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

उदाहरण के लिए:

some_guy = 'Fred'
# ...
some_guy = 'George'

जब हम बाद में some_guy = 'जॉर्ज' कहते हैं, तो 'फ्रेड' युक्त स्ट्रिंग ऑब्जेक्ट अप्रभावित है। हमने कुछ_गुवाई नाम के बंधन को बदल दिया है। हालाँकि, हमने 'फ्रेड' या 'जॉर्ज' स्ट्रिंग ऑब्जेक्ट्स को नहीं बदला है। जहां तक ​​हमारा संबंध है, वे अनिश्चित काल तक रह सकते हैं।

ब्लॉग से लिंक करें: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/


1

उपर्युक्त उत्तरों में थोड़ा और जोड़ना।

id पुनर्मूल्यांकन पर परिवर्तनशील परिवर्तन।

>>> a = 'initial_string'
>>> id(a)
139982120425648
>>> a = 'new_string'
>>> id(a)
139982120425776

जिसका अर्थ है कि हमने aएक नए स्ट्रिंग को इंगित करने के लिए चर को उत्परिवर्तित किया है । अब दो string (str) ऑब्जेक्ट मौजूद हैं:

'initial_string' साथ में id= 139982120425648 के

तथा

'new_string'id= 139982120425776 के साथ

नीचे दिए गए कोड पर विचार करें:

>>> b = 'intitial_string'
>>> id(b)
139982120425648

अब, पुनर्मूल्यांकन से पहले के समान है और bइंगित करता है ।'initial_string'ida

इस प्रकार, 'intial_string'उत्परिवर्तित नहीं किया गया है।


0

सारांश:

a = 3
b = a
a = 3+2
print b
# 5

अपरिवर्तनीय नहीं:

a = 'OOP'
b = a
a = 'p'+a
print b
# OOP

अपरिवर्तनीय:

a = [1,2,3]
b = range(len(a))
for i in range(len(a)):
    b[i] = a[i]+1

यह पायथन 3 में एक त्रुटि है क्योंकि यह अपरिवर्तनीय है। और पायथन 2 में कोई त्रुटि नहीं क्योंकि स्पष्ट रूप से यह अपरिवर्तनीय नहीं है।


0

अंतर्निहित फ़ंक्शन id()किसी ऑब्जेक्ट की पहचान को पूर्णांक के रूप में लौटाता है। यह पूर्णांक आमतौर पर मेमोरी में ऑब्जेक्ट के स्थान से मेल खाता है।

\>>a='dog'
\>>print(id(a))

139831803293008

\>>a=a+'cat'
\>>print(id(a))

139831803293120

प्रारंभ में, 'a' को 139831803293008 मेमोरी लोकेशन में स्टोर किया जाता है, क्योंकि स्ट्रिंग ऑब्जेक्ट अजगर में अपरिवर्तनीय है यदि आप संदर्भ को संशोधित करने और पुन: असाइन करने का प्रयास करते हैं तो हटा दिया जाएगा और एक नए मेमोरी लोकेशन (139831803293120) के लिए एक पॉइंटर होगा।


0
a = 'dog'
address = id(a)
print(id(a))

a = a + 'cat'
print(id(a))      #Address changes

import ctypes
ctypes.cast(address, ctypes.py_object).value    #value at old address is intact

2
हालांकि यह कोड ओपी के मुद्दे को हल कर सकता है, लेकिन स्पष्टीकरण को शामिल करना सबसे अच्छा है कि आपका कोड ओपी के मुद्दे को कैसे संबोधित करता है। इस तरह, भविष्य के आगंतुक आपके पोस्ट से सीख सकते हैं, और इसे अपने कोड पर लागू कर सकते हैं। SO एक कोडिंग सेवा नहीं है, बल्कि ज्ञान के लिए एक संसाधन है। इसके अलावा, उच्च गुणवत्ता, पूर्ण उत्तरों के अपग्रेड होने की अधिक संभावना है। ये विशेषताएं, इस आवश्यकता के साथ कि सभी पद स्व-सम्‍मिलित हैं, एसओ की कुछ ताकतें एक मंच के रूप में हैं, जो इसे मंचों से अलग करती हैं। आप अतिरिक्त जानकारी जोड़ने और / या स्रोत प्रलेखन के साथ अपनी व्याख्याओं को पूरक करने के लिए संपादित कर सकते हैं
शेरलहोमन


-1

हम दो स्ट्रिंग मानों को समेटते हैं। हम कभी भी (a) का मान नहीं बदलते हैं। अभी (ए) एक अन्य मेमोरी ब्लॉक का प्रतिनिधित्व करता है जिसमें "डॉगडॉग" मूल्य है। क्योंकि बैकएंड में, एक चर एक ही समय में दो मेमोरी ब्लॉकों का प्रतिनिधित्व नहीं करता है। संघनन से पहले (ए) का मूल्य "कुत्ता" था। लेकिन उसके बाद (ए) "डॉगडॉग" का प्रतिनिधित्व करते हैं, क्योंकि अब (ए) बैकएंड प्रतिनिधि में है। ब्लॉक जिसमें "डॉगडॉग" मूल्य है। और "कुत्ता" प्रतिनिधि है। द्वारा (बी) और "कुत्ते" को तब तक कचरा मूल्य के रूप में नहीं गिना जाता है जब तक (बी) "कुत्ते" का प्रतिनिधित्व नहीं करते हैं।

भ्रम यह है कि हम एक ही चर नाम के साथ बैकएंड में मेमोरी ब्लॉक्स (जिसमें डेटा या जानकारी शामिल है) का प्रतिनिधित्व करते हैं।


-2

आप एक सुस्पष्ट सरणी को अपरिवर्तनीय बना सकते हैं और पहले तत्व का उपयोग कर सकते हैं:

numpyarrayname[0] = "write once"

फिर:

numpyarrayname.setflags(write=False)

या

numpyarrayname.flags.writeable = False
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.