अपरिवर्तनीय बनाम म्यूटेबल प्रकार


184

मैं उलझन में हूँ कि एक अपरिवर्तनीय प्रकार क्या है। मुझे पता है कि floatवस्तु को अपरिवर्तनीय माना जाता है, इस प्रकार के उदाहरण मेरी पुस्तक से:

class RoundFloat(float):
    def __new__(cls, val):
        return float.__new__(cls, round(val, 2))

क्या इसे वर्ग संरचना / पदानुक्रम के कारण अपरिवर्तनीय माना जाता है ?, अर्थ floatवर्ग के शीर्ष पर है और इसकी स्वयं की विधि कॉल है। इस प्रकार के उदाहरण के समान (भले ही मेरी पुस्तक कहे जाने योग्य dictहै):

class SortedKeyDict(dict):
    def __new__(cls, val):
        return dict.__new__(cls, val.clear())

जबकि इस प्रकार के उदाहरण के साथ, कुछ उत्परिवर्तनीय तरीके कक्षा के अंदर हैं:

class SortedKeyDict_a(dict):
    def example(self):
        return self.keys()

इसके अलावा, अंतिम के लिए class(SortedKeyDict_a), यदि मैं इस प्रकार के सेट को पास करता हूं:

d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))

exampleविधि को बुलाए बिना , यह एक शब्दकोश देता है। SortedKeyDictसाथ __new__एक त्रुटि के रूप में झंडे यह। मैंने RoundFloatकक्षा में पूर्णांकों को पास करने की कोशिश की __new__और इसमें कोई त्रुटि नहीं थी।


आप कॉपी.कॉपी का उपयोग करने के लिए [:] और अजगर के साथ सूची असाइनमेंट की भी जांच कर सकते हैं, जिसका मैंने भी जवाबदेही के लिए अधिक जानकारी के लिए उत्तर दिया था।
एजी

जवाबों:


230

क्या? फ़्लोट्स अपरिवर्तनीय हैं? लेकिन मैं नहीं कर सकता

x = 5.0
x += 7.0
print x # 12.0

कि "म्यूट" एक्स नहीं है?

वैसे आप सहमत हैं कि तार अपरिवर्तनीय हैं? लेकिन आप एक ही काम कर सकते हैं।

s = 'foo'
s += 'bar'
print s # foobar

परिवर्तनशील चर का मान बदलता है, लेकिन परिवर्तन चर को संदर्भित करता है। एक परिवर्तनशील प्रकार उस तरह से बदल सकता है, और यह "जगह में" भी बदल सकता है ।

यहाँ अंतर है।

x = something # immutable type
print x
func(x)
print x # prints the same thing

x = something # mutable type
print x
func(x)
print x # might print something different

x = something # immutable type
y = x
print x
# some statement that operates on y
print x # prints the same thing

x = something # mutable type
y = x
print x
# some statement that operates on y
print x # might print something different

ठोस उदाहरण

x = 'foo'
y = x
print x # foo
y += 'bar'
print x # foo

x = [1, 2, 3]
y = x
print x # [1, 2, 3]
y += [3, 2, 1]
print x # [1, 2, 3, 3, 2, 1]

def func(val):
    val += 'bar'

x = 'foo'
print x # foo
func(x)
print x # foo

def func(val):
    val += [3, 2, 1]

x = [1, 2, 3]
print x # [1, 2, 3]
func(x)
print x # [1, 2, 3, 3, 2, 1]

5
आप मुझे क्या समझाते हैं: परस्पर परिवर्तनशील चर संदर्भ द्वारा पारित किए जाते हैं, अपरिवर्तनीय चर मूल्य द्वारा पारित किए जाते हैं। क्या ये सही है ?
लॉरेंज मेयर

16
लगभग, लेकिन बिल्कुल नहीं। तकनीकी रूप से, सभी चर को पायथन में संदर्भ द्वारा पारित किया जाता है, लेकिन सी में मान से पास होने की तरह एक शब्दार्थ अधिक होता है def f(my_list): my_list = [1, 2, 3]। यदि आप करते हैं तो आपकी सादृश्य के लिए एक प्रतिधारण है । C में पास-बाय-रेफरेंस के साथ, उस फ़ंक्शन को कॉल करके तर्क का मान बदल सकता है। पायथन में, वह फ़ंक्शन कुछ भी नहीं करता है। def f(my_list): my_list[:] = [1, 2, 3]कुछ करेगा।
मॉर्निंगस्टार

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

13
पायथन के शब्दार्थ और C ++ पास-बाय-रेफरेंस शब्दार्थ के बीच महत्वपूर्ण अंतर यह है कि असाइनमेंट पायथन में उत्परिवर्तन नहीं है, और यह C ++ में है। (लेकिन निश्चित रूप से तथ्य यह है कि, असाइनमेंट संवर्धित तरह से जटिल है कि a += bकभी कभी है , उत्परिवर्तन। और इस तथ्य है एक बड़ा वस्तु का हिस्सा करने के लिए काम कभी कभी कि बड़े वस्तु के उत्परिवर्तन, बस कभी नहीं पार्ट-जैसे के उत्परिवर्तन का मतलब है कि a[0] = bउत्परिवर्तन नहीं है a[0], लेकिन यह शायद मे बदलें करता है a... इसीलिए यह बेहतर हो सकता है नहीं सी के मामले में ++ बातें डाल करने के लिए प्रयास करने के लिए और इसके बजाय सिर्फ वर्णन अजगर अपने स्वयं के संदर्भ में क्या करता है ...)
abarnert

2
मुझे यह उत्तर भ्रामक लगा क्योंकि इसमें id () का उपयोग नहीं किया गया है, जो कि अपरिवर्तनीय साधनों को समझने के लिए आवश्यक है।
पावेल_विनजिग

183

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

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

>>> s = "abc"
>>>id(s)
4702124
>>> s[0] 
'a'
>>> s[0] = "o"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> s = "xyz"
>>>id(s)
4800100
>>> s += "uvw"
>>>id(s)
4800500

आप एक सूची के साथ ऐसा कर सकते हैं और यह वस्तुओं की पहचान को नहीं बदलेगा

>>> i = [1,2,3]
>>>id(i)
2146718700
>>> i[0] 
1
>>> i[0] = 7
>>> id(i)
2146718700

पायथन के डेटा मॉडल के बारे में अधिक पढ़ने के लिए आप पायथन भाषा संदर्भ पर एक नज़र डाल सकते हैं:


4
+1 पायथन डॉक्स के लिंक के लिए। हालाँकि मुझे कुछ समय लगा जब तक मुझे एहसास हुआ कि आज आपको पाइथन 2 और 3 को अलग करने की आवश्यकता है - मैंने उस पर जोर देने के लिए उत्तर को अपडेट किया।
बेंजामिन

106

सामान्य अपरिवर्तनीय प्रकार:

  1. संख्या: int(), float(),complex()
  2. अपरिवर्तनीय दृश्यों: str(), tuple(), frozenset(),bytes()

सामान्य परिवर्तनशील प्रकार (लगभग सब कुछ):

  1. परिवर्तनशील दृश्यों: list(),bytearray()
  2. सेट प्रकार: set()
  3. मानचित्रण प्रकार: dict()
  4. कक्षाएं, वर्ग उदाहरण
  5. आदि।

एक प्रकार से जल्दी से परीक्षण करने के लिए एक चाल है कि क्या कोई परिवर्तनशील है या नहीं, id()अंतर्निहित फ़ंक्शन का उपयोग करना है।

पूर्णांक पर उपयोग करते हुए, उदाहरण

>>> i = 1
>>> id(i)
***704
>>> i += 1
>>> i
2
>>> id(i)
***736 (different from ***704)

सूची का उपयोग करना,

>>> a = [1]
>>> id(a)
***416
>>> a.append(2)
>>> a
[1, 2]
>>> id(a)
***416 (same with the above id)

11
अच्छी तरह समझाया। द्वारा जाँच की अवधारणा पसंद आई id()। +1।
पराग त्यागी

4
वास्तव में यहाँ का उपयोग id()भ्रामक है। एक दी गई वस्तु हमेशा अपने जीवनकाल के दौरान एक ही आईडी होगी, लेकिन अलग-अलग समय पर मौजूद विभिन्न वस्तुओं में कचरा संग्रह के कारण एक ही आईडी हो सकती है।
अगस्तुर

36

सबसे पहले, एक वर्ग के तरीके हैं या क्या यह वर्ग संरचना है, इसका उत्परिवर्तन से कोई लेना-देना नहीं है।

ints और floats अपरिवर्तनीय हैं । यदि मैं करता हूँ

a = 1
a += 5

यह नाम बताते हैं aएक में 1पहली पंक्ति पर स्मृति में कहीं। दूसरी पंक्ति में, यह दिखता है कि 1, जोड़ता है 5, प्राप्त करता है 6, फिर उस बिंदु aपर 6स्मृति में - यह किसी भी तरह से एक को नहीं बदलता है । अन्य अपरिवर्तनीय प्रकारों का उपयोग करके एक ही तर्क निम्न उदाहरणों पर लागू होता है :16

b = 'some string'
b += 'some other string'
c = ('some', 'tuple')
c += ('some', 'other', 'tuple')

के लिए अस्थायी प्रकार, मैं बात यह है कि actallly कर सकते हैं जहां यह स्मृति में संग्रहीत है मान परिवर्तित । साथ में:

d = [1, 2, 3]

मैं के स्थानों की एक सूची बनाई है 1, 2और 3स्मृति में। अगर मैं करता हूँ

e = d

मैं बस eएक हीlist d बिंदु पर इंगित करता हूं । मैं तब कर सकता हूं:

e += [4, 5]

और सूची है कि दोनों eऔर dबिंदुओं को अद्यतन किया जाएगा भी स्मृति में 4और स्थानों पर है 5

अगर मैं एक अपरिवर्तनीय प्रकार पर वापस जाता हूं और ऐसा करता हूं tuple:

f = (1, 2, 3)
g = f
g += (4, 5)

फिर fभी केवल मूल कीtuple ओर इशारा करता है - आपने पूरी तरह से नएg पर इशारा किया है ।tuple

अब, आपके उदाहरण के साथ

class SortedKeyDict(dict):
    def __new__(cls, val):
        return dict.__new__(cls, val.clear())

जहां तुम गुजरते हो

d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2))

(एक है जो tupleकी tuplesके रूप में) val, क्योंकि आपको एक त्रुटि हो रही है tupleएक की जरूरत नहीं है .clear()विधि - आप पारित करने के लिए होगा dict(d)के रूप में valकाम करने के लिए इसके लिए, इस स्थिति में आप एक खाली मिल जाएगा SortedKeyDictएक परिणाम के रूप।


2
यह बहुत अच्छी व्याख्या है। इस सवाल को पसंद किया और इसे समझाने के लिए बहुत सारे दिलचस्प (नए) दृष्टिकोण।
असफल वैज्ञानिक

24

यदि आप दूसरी भाषा से अजगर के पास आ रहे हैं (एक को छोड़कर, जो कि अजगर की तरह है, जैसे रूबी), और इसे उस दूसरी भाषा के संदर्भ में समझने पर जोर देते हैं, तो यहां लोग आमतौर पर भ्रमित होते हैं:

>>> a = 1
>>> a = 2 # I thought int was immutable, but I just changed it?!

पायथन में, पायथन में असाइनमेंट म्यूटेशन नहीं है।

C ++ में, यदि आप लिखते हैं a = 2, तो आप कॉल कर रहे हैं a.operator=(2), जो संग्रहित ऑब्जेक्ट को म्यूट करेगा a। (और अगर वहाँ कोई वस्तु संग्रहीत नहीं थीa , तो यह एक त्रुटि है।)

पायथन में, a = 2जो कुछ भी संग्रहीत किया गया था , उसके लिए कुछ भी नहीं करता है a; इसका मतलब सिर्फ इतना है कि 2अब aइसके बजाय संग्रहीत किया जाता है। (और अगर वहाँ कोई वस्तु संग्रहीत नहीं थीa , तो यह ठीक है।)


अंततः, यह एक और भी गहरे अंतर का हिस्सा है।

C ++ जैसी भाषा में एक चर स्मृति में एक टाइप किया गया स्थान है। यदि aकोई है int, तो इसका मतलब यह है कि यह 4 बाइट्स है जो कंपाइलर जानता है कि इसकी व्याख्या की जानी चाहिए int। इसलिए, जब आप ऐसा करते हैं a = 2, तो यह बदल जाता है कि मेमोरी के उन 4 बाइट्स में क्या संग्रहीत किया 0, 0, 0, 1जाता है 0, 0, 0, 2। यदि कहीं और एक अन्य चर है, तो इसकी अपनी 4 बाइट्स हैं।

पायथन जैसी भाषा में एक चर एक वस्तु का एक नाम है जिसका अपना जीवन है। संख्या के लिए एक वस्तु है 1, और संख्या के लिए दूसरी वस्तु है 2। और aस्मृति के 4 बाइट्स नहीं हैं जिन्हें एक के रूप में दर्शाया गया है int, यह सिर्फ एक नाम है जो 1ऑब्जेक्ट पर इंगित करता है। यह a = 2संख्या 2 को नंबर 2 में बदलने के लिए कोई मतलब नहीं है (जो किसी भी पायथन प्रोग्रामर को ब्रह्मांड के मौलिक कामकाज को बदलने के लिए बहुत अधिक शक्ति देगा); इसके बजाय यह क्या करता है बस वस्तु को aभूल जाओ 1और 2इसके बजाय वस्तु को इंगित करो ।


इसलिए, यदि असाइनमेंट म्यूटेशन नहीं है, तो म्यूटेशन क्या है ?

  • एक ऐसी विधि को कॉल करना जो म्यूट करने के लिए प्रलेखित है, जैसे a.append(b)। (ध्यान दें कि ये विधियाँ लगभग हमेशा लौटती हैं None)। अपरिवर्तनीय प्रकारों में ऐसी कोई विधियाँ नहीं होती हैं, जो परिवर्तनशील प्रकार आमतौर पर होती हैं।
  • वस्तु के एक भाग को निर्दिष्ट करना, जैसे a.spam = bया a[0] = b। अपरिवर्तनीय प्रकार विशेषता या तत्वों को असाइन करने की अनुमति नहीं देते हैं, परिवर्तनशील प्रकार आमतौर पर एक या दूसरे को अनुमति देते हैं।
  • कभी-कभी संवर्धित असाइनमेंट का उपयोग करना, जैसे a += b, कभी-कभी नहीं। म्यूटेबल प्रकार आमतौर पर मूल्य को उत्परिवर्तित करते हैं; अपरिवर्तनीय प्रकार कभी नहीं करते हैं, और आपको इसके बजाय एक प्रति देते हैं (वे गणना करते हैं a + b, फिर परिणाम असाइन करें a)।

लेकिन अगर असाइनमेंट म्यूटेशन नहीं है, तो ऑब्जेक्ट म्यूटेशन के हिस्से को कैसे असाइन किया जा रहा है? बस यहीं से मुश्किल हो जाती है। म्यूट नहींa[0] = b करता है (फिर से, सी ++ के विपरीत), लेकिन यह म्यूटेट करता है (सी ++ के विपरीत, अप्रत्यक्ष रूप से छोड़कर)।a[0]a

यह सब इसीलिए संभव है कि आप जिस भाषा के लिए अभ्यस्त हैं , उसके संदर्भ में पाइथन के शब्दार्थ को डालने की कोशिश करें, और इसके बजाय अपनी शर्तों पर पाइथन के शब्दार्थ को जानें।


2
कह ए = 'हाय'। एक [0] = 'f' में 'प्रिंट आउट' 'फाई' होगा (क्या मैं अभी तक सही हूँ?), इसलिए जब आप कहते हैं कि यह एक [०] को म्यूट नहीं करता है, बल्कि, इसका क्या मतलब है? ? क्या [n] के पास भी अब अपना स्थान है, और इसके मूल्य को बदलने से यह एक अलग मूल्य है?
डेनियल स्प्रिंगर

19

कोई वस्तु उत्परिवर्तनीय है या नहीं यह उसके प्रकार पर निर्भर करता है। यह इस बात पर निर्भर नहीं करता है कि इसकी कुछ विधियाँ हैं या नहीं, और न ही वर्ग पदानुक्रम की संरचना पर।

उपयोगकर्ता-परिभाषित प्रकार (यानी कक्षाएं) आम तौर पर पारस्परिक हैं। कुछ अपवाद हैं, जैसे एक अपरिवर्तनीय प्रकार के सरल उप-वर्ग। अन्य अपरिवर्तनीय प्रकार में शामिल कुछ बिल्ट-इन जैसे प्रकार int, float, tupleऔर str, साथ ही कुछ अजगर कक्षाएं सी में लागू किया

पायथन भाषा संदर्भ में "डेटा मॉडल" अध्याय से एक सामान्य व्याख्या :

कुछ वस्तुओं का मूल्य बदल सकता है। जिन वस्तुओं के मूल्य में परिवर्तन हो सकता है, उन्हें परस्पर कहा जा सकता है; जिन वस्तुओं का मूल्य एक बार बनाए जाने के बाद अपरिवर्तनीय होता है, उन्हें अपरिवर्तनीय कहा जाता है।

(एक अपरिवर्तनीय कंटेनर ऑब्जेक्ट का मूल्य जिसमें एक परिवर्तनशील वस्तु का संदर्भ होता है, जब बाद के मूल्य को बदल दिया जा सकता है, हालांकि कंटेनर को अभी भी अपरिवर्तनीय माना जाता है, क्योंकि इसमें शामिल वस्तुओं के संग्रह को बदला नहीं जा सकता है। इसलिए, अपरिवर्तनीयता सख्ती से नहीं है। एक अपरिवर्तनीय मूल्य होने के समान, यह अधिक सूक्ष्म है।)

किसी वस्तु की उत्परिवर्तन उसके प्रकार से निर्धारित होती है; उदाहरण के लिए, संख्याएँ, तार और टुपल्स अपरिवर्तनीय हैं, जबकि शब्दकोष और सूचियाँ परस्पर हैं।


+1 नोट हालांकि केवल कुछ एक्सटेंशन प्रकार (आप अपनी परिभाषा की समीक्षा करना चाहते हैं, पायथन के सभी प्रकार के C को लागू किया गया है) अपरिवर्तनीय हैं। अन्य (सबसे, मैं कहने की हिम्मत करूँगा) पूरी तरह से परस्पर हैं।

@delnan आप "एक्सटेंशन प्रकार" को क्या कहते हैं ?
23

@eyquem: मैंने अपने उत्तर में "एक्सटेंशन प्रकार" शब्द का गलत तरीके से उपयोग किया था, और डेलान का उल्लेख था। उनकी टिप्पणी के बाद मैंने अपने उत्तर को संशोधित किया और इस शब्द का उपयोग करने से बचा।
8

19

Mutable और Immutable ऑब्जेक्ट के बीच अंतर

परिभाषाएं

म्यूटेबल ऑब्जेक्ट : ऑब्जेक्ट जो इसे बनाने के बाद बदला जा सकता है।
अपरिवर्तनीय वस्तु : वह वस्तु जिसे बनाने के बाद उसे बदला नहीं जा सकता।

अजगर में अपरिवर्तनीय वस्तु के मूल्य को बदलने की कोशिश करेगा यह नई वस्तु देगा।

परस्पर वस्तु

यहाँ अजगर में सूची वस्तुएँ हैं जो परस्पर प्रकार की हैं:

  1. list
  2. Dictionary
  3. Set
  4. bytearray
  5. user defined classes

अपरिवर्तनीय वस्तुएँ

यहाँ अजगर में सूची वस्तुएँ हैं जो अपरिवर्तनीय प्रकार की हैं:

  1. int
  2. float
  3. decimal
  4. complex
  5. bool
  6. string
  7. tuple
  8. range
  9. frozenset
  10. bytes

कुछ अनुत्तरित प्रश्न

प्रश्न : क्या स्ट्रिंग एक अपरिवर्तनीय प्रकार है?
उत्तर : हाँ यह है, लेकिन क्या आप इसे समझा सकते हैं: प्रमाण 1 :

a = "Hello"
a +=" World"
print a

उत्पादन

"Hello World"

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

a = "Hello"
identity_a = id(a)
a += " World"
new_identity_a = id(a)
if identity_a != new_identity_a:
    print "String is Immutable"

उत्पादन

String is Immutable

प्रमाण 2 :

a = "Hello World"
a[0] = "M"

उत्पादन

TypeError 'str' object does not support item assignment

प्रश्न : क्या टपल एक अपरिवर्तनीय प्रकार है?
उत्तर : हाँ यह सबूत 1 है :

tuple_a = (1,)
tuple_a[0] = (2,)
print a

उत्पादन

'tuple' object does not support item assignment

[४६]: ए = "हेलो" में [४ id]: आईडी (ए) आउट [४:]: १४००12१२६३ [48०१२] [४01] में: ए = a.replace ("एच", "जी") [४ ९] में: आउट [४ ९]: [५०] में lo गेलो ’: आईडी (ए) आउट [५०]: १४००12१२६३ Ar Ar१०४०
आरगस मालवेयर १ '

क्या आप अपने आइटम असाइनमेंट इशू को मेरे ऊपर दिए गए उदाहरण से प्रमाणित करने की परवाह करेंगे
Argus Malware

आइटम असाइनमेंट अपरिवर्तनीय प्रकारों में समस्या नहीं है। आपके मामले में आप स्ट्रिंग को बदल रहे हैं लेकिन स्मृति में एक नए चर को असाइन करना। मेरे मामले में आइटम असाइनमेंट सूची या शब्दकोश के मामले में चर की स्मृति को नहीं बदलेगा। यदि आप प्रतिस्थापित कर रहे हैं तो आप एक नया चर बना रहे हैं जो मौजूदा चर को संशोधित नहीं कर रहा है
औरंड त्रिपाठी

आपके मामले में @ArgusMalware, GC द्वारा पुनर्नवीनीकरण किए गए पहले एक के कारण दो आईडी बराबर हैं, इसलिए दूसरा एक मेमोरी का पुनः उपयोग करता है।
कोलोरल

11

एक उत्परिवर्तित वस्तु में कम से कम एक विधि होती है जो वस्तु को उत्परिवर्तित करने में सक्षम होती है। उदाहरण के लिए, listऑब्जेक्ट में वह appendविधि है, जो वास्तव में ऑब्जेक्ट को म्यूट करेगी:

>>> a = [1,2,3]
>>> a.append('hello') # `a` has mutated but is still the same object
>>> a
[1, 2, 3, 'hello']

लेकिन क्लास floatमें फ्लोट ऑब्जेक्ट को म्यूट करने की कोई विधि नहीं है। तुम कर सकते हो:

>>> b = 5.0 
>>> b = b + 0.1
>>> b
5.1

लेकिन =ऑपरेंड एक विधि नहीं है। यह सिर्फ चर के बीच एक बंधन बनाता है और जो कुछ भी इसके दाईं ओर है, कुछ और नहीं। यह कभी भी वस्तुओं को बदलता या बनाता नहीं है। यह इस बात की घोषणा है कि चर अब किस ओर इशारा करेगा।

जब आप ऐसा करेंगे संकार्य एक नई नाव, जो की ते परिणाम के साथ बनाई गई है करने के लिए चर बांधता है ।b = b + 0.1=5 + 0.1

जब आप किसी चर को किसी विद्यमान वस्तु में बदलते हैं, तो परस्पर या नहीं, =ऑपरेंड उस वस्तु को चर बांधता है। और कुछ नहीं होता

किसी भी मामले में, =बस बाँध बनाते हैं। यह वस्तुओं को बदलता या नहीं बनाता है।

जब आप करते हैं a = 1.0, तो =ऑपरेंड विच फ्लोट नहीं बनाता है, लेकिन 1.0लाइन का हिस्सा होता है। असल में जब आप लिखते हैं तो 1.0यह float(1.0)एक फ्लोट ऑब्जेक्ट को लौटाने वाले कंस्ट्रक्टर कॉल के लिए शॉर्टहैंड होता है । (यही कारण है कि अगर आप टाइप करते हैं 1.0और एंटर दबाते हैं तो आपको 1.0नीचे दी गई "इको" मिलती है ; यह आपके द्वारा कहे गए कंस्ट्रक्टर फ़ंक्शन का रिटर्न वैल्यू है)

अब, यदि bकोई फ्लोट है और आप असाइन करते हैं a = b, तो दोनों चर एक ही वस्तु की ओर इशारा करते हैं, लेकिन वास्तव में चर खुद को धोखा नहीं दे सकते हैं, क्योंकि ऑब्जेक्ट अयोग्य है, और यदि आप करते हैं b += 1, तो bएक नई वस्तु की ओर इशारा करते हैं , और aहै अभी भी पुराने की ओर इशारा कर रहा है और यह नहीं बता सकता कि किस bओर इशारा कर रहा है।

लेकिन अगर cहै, तो हम कहते हैं, listऔर आप असाइन करते हैं a = c, अब कर सकते हैं aऔर c"कॉम्युनिकेट" कर सकते हैं, क्योंकि listयह परिवर्तनशील है, और यदि आप करते हैं c.append('msg'), तो बस चेक करने से aआपको संदेश मिलता है।

(वैसे, हर वस्तु की एक विशिष्ट आईडी संख्या होती है, जिसे आप प्राप्त कर सकते हैं id(x)। इसलिए आप जांच सकते हैं कि कोई वस्तु समान है या नहीं जाँच रही है कि उसकी अद्वितीय आईडी बदल गई है या नहीं।)


6

एक वर्ग अपरिवर्तनीय होता है यदि उस वर्ग के प्रत्येक ऑब्जेक्ट में तात्कालिकता पर एक निश्चित मूल्य होता है जो SUBSEQUENTLY नहीं बदला जा सकता है

दूसरे शब्द में उस चर के पूरे मान को बदल (name)दें या उसे अकेला छोड़ दें।

उदाहरण:

my_string = "Hello world" 
my_string[0] = "h"
print my_string 

आपको यह उम्मीद है कि यह काम करेगा और हैलो वर्ल्ड प्रिंट करेगा, लेकिन यह निम्नलिखित त्रुटि को दूर करेगा:

Traceback (most recent call last):
File "test.py", line 4, in <module>
my_string[0] = "h"
TypeError: 'str' object does not support item assignment

दुभाषिया कह रहा है: मैं इस स्ट्रिंग के पहले चरित्र को नहीं बदल सकता

stringकाम करने के लिए आपको इसे पूरा बदलना होगा :

my_string = "Hello World" 
my_string = "hello world"
print my_string #hello world

इस तालिका की जाँच करें:

यहां छवि विवरण दर्ज करें

स्रोत


ऊपर दिखाए गए की तुलना में एक अजगर स्ट्रिंग के घटकों को अधिक संक्षिप्त तरीके से कैसे संशोधित किया जा सकता है?
ल्यूक डेविस

@LukeDavis आप कर सकते हैं my_string = 'h' + my_string[1:]। यह my_string नामक एक नया स्ट्रिंग उत्पन्न करेगा, और मूल my_string चला गया है ( id(my_string)यह देखने के लिए प्रिंट करें)। निश्चित रूप से यह बहुत लचीला नहीं है, और अधिक सामान्य मामले के लिए आप सूची और पीठ में परिवर्तित कर सकते हैं:l = list(my_string) l[0] = 'h' my_string = ''.join(l)
danio

5

यह मुझे प्रतीत होगा कि आप इस प्रश्न से लड़ रहे हैं कि वास्तव में क्या परिवर्तनशील / अपरिवर्तनीय है । तो यहाँ एक सरल खोज है:

पहले हमें अन्वेषण पर आधारित करने के लिए एक नींव की आवश्यकता है।

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

उदाहरण के लिए आप 0x110, 0xaf0278297319 या इसी तरह की संख्याओं के बारे में नहीं सोचते हैं, बल्कि आप संख्याओं के बारे में सोचते हैं जैसे 6 या स्ट्रिंग्स जैसे "हैलो, दुनिया"। कभी भी कम थिसिस नंबर या स्ट्रिंग्स कंप्यूटर मेमोरी में बाइनरी नंबर की व्याख्या नहीं है। एक चर के किसी भी मूल्य के लिए भी यही सच है।

संक्षेप में: हम वास्तविक मूल्यों के साथ नहीं बल्कि वास्तविक द्विआधारी मूल्यों की व्याख्या के साथ कार्यक्रम करते हैं।

अब हमारे पास व्याख्याएं हैं जिन्हें तर्क और अन्य "साफ-सुथरे सामान" के लिए नहीं बदला जाना चाहिए, जबकि ऐसी व्याख्याएं हैं जो अच्छी तरह से बदली जा सकती हैं। उदाहरण के लिए एक शहर के अनुकरण के बारे में सोचें, दूसरे शब्दों में एक कार्यक्रम जहां कई आभासी वस्तुएं हैं और इनमें से कुछ घर हैं। अब इन आभासी वस्तुओं (घरों) को बदला जा सकता है और क्या उन्हें अभी भी एक ही घर माना जा सकता है? बेशक वे कर सकते हैं। इस प्रकार वे परिवर्तनशील हैं: उन्हें "पूरी तरह से" अलग वस्तु के बिना बदला जा सकता है।

अब पूर्णांकों के बारे में सोचें: ये भी आभासी वस्तुएं हैं (कंप्यूटर मेमोरी में बाइनरी संख्याओं के अनुक्रम)। इसलिए यदि हम उनमें से एक को बदलते हैं, जैसे कि मूल्य को छह से बढ़ाना, क्या यह अभी भी एक छह है? खैर नहीं। इस प्रकार कोई भी पूर्णांक अपरिवर्तनीय है।

इसलिए: यदि किसी आभासी वस्तु में कोई परिवर्तन होता है तो इसका मतलब है कि यह वास्तव में एक और आभासी वस्तु बन जाती है, तो इसे अपरिवर्तनीय कहा जाता है।

अंतिम टिप्पणी:

(1) एक निश्चित भाषा में प्रोग्रामिंग के साथ परस्पर और अपरिवर्तनीय के अपने वास्तविक दुनिया के अनुभव को कभी भी न मिलाएं:

हर प्रोग्रामिंग लैंग्वेज की अपनी एक परिभाषा होती है, जिस पर वस्तुओं को म्यूट किया जा सकता है और जो नहीं हो सकता है।

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

(२) यह अन्वेषण निश्चित रूप से वैज्ञानिक नहीं है, इसका मतलब है कि आप परस्पर और अपरिवर्तनीय के बीच के अंतर को समझ सकते हैं।


5

इस उत्तर का लक्ष्य सभी अच्छे विचारों को खोजने के लिए एक ही जगह बनाना है कि कैसे बताएं कि आप म्यूटिंग / नॉनम्यूटिंग (अपरिवर्तनीय / परिवर्तनशील) के साथ काम कर रहे हैं और कहां संभव है, इसके बारे में क्या करना है? ऐसे समय होते हैं जब उत्परिवर्तन अवांछनीय होता है और इस संबंध में अजगर का व्यवहार अन्य भाषाओं से आने वाले कोडर्स के प्रति सहज-सहज महसूस कर सकता है।

@ मिना-गैब्रिएल द्वारा एक उपयोगी पोस्ट के अनुसार:

उपरोक्त का विश्लेषण और @ arrakëën द्वारा w / एक पोस्ट का संयोजन:

अप्रत्याशित रूप से क्या नहीं बदल सकता है?

  • स्केलर (एक एकल मान को संग्रहीत करने वाले चर प्रकार) अप्रत्याशित रूप से नहीं बदलते हैं
    • संख्यात्मक उदाहरण: int (), फ्लोट (), जटिल ()
  • कुछ "परिवर्तनशील अनुक्रम" हैं:
    • str (), tuple (), Frozenset (), बाइट्स ()

क्या हो सकता हैं?

  • वस्तुओं की सूची (सूची, शब्दकोश, सेट, बायट्रे) ()
  • यहाँ पर एक पोस्ट भी कहती है कि क्लास और क्लास इंस्टेंसेस लेकिन यह इस बात पर निर्भर हो सकता है कि क्लास को क्या विरासत में मिला है और / या कैसे बनाया गया है।

"अप्रत्याशित रूप से" से मेरा मतलब है कि अन्य भाषाओं के प्रोग्रामर इस व्यवहार (अपवाद या रूबी के साथ, और शायद कुछ अन्य "पायथन जैसे" भाषाओं) की उम्मीद नहीं कर सकते हैं।

इस चर्चा में जोड़ना:

यह व्यवहार एक फायदा है जब यह आपको गलती से अपने कोड को स्मृति-खाने वाले बड़े डेटा संरचनाओं की उत्परिवर्ती प्रतियों के साथ आबाद करने से रोकता है। लेकिन जब यह अवांछनीय है, तो हम इसे कैसे प्राप्त कर सकते हैं?

सूचियों के साथ, सरल समाधान एक नया निर्माण करना है जैसे:

सूची 2 = सूची (सूची 1)

अन्य संरचनाओं के साथ ... समाधान पेचीदा हो सकता है। एक तरीका तत्वों के माध्यम से लूप करना है और उन्हें एक नए खाली डेटा संरचना (उसी प्रकार का) में जोड़ना है।

जब आप उत्परिवर्तनीय संरचनाओं में पास होते हैं तो फ़ंक्शंस मूल को म्यूट कर सकते हैं। कैसे कहो?

  • इस थ्रेड पर अन्य टिप्पणियों पर कुछ परीक्षण दिए गए हैं, लेकिन फिर ऐसी टिप्पणियां हैं जो इन परीक्षणों का पूर्ण प्रमाण नहीं हैं
  • object.function () मूल वस्तु का एक तरीका है, लेकिन इनमें से केवल कुछ उत्परिवर्तित होते हैं। यदि वे कुछ भी नहीं लौटाते हैं, तो वे शायद करते हैं। कोई भी .append () को उसके नाम दिए बिना परीक्षण के लिए म्यूट करने की उम्मीद करेगा। .union () set1.union (सेट 2) का संघ लौटाता है और म्यूट नहीं करता है। जब संदेह होता है, तो फ़ंक्शन को रिटर्न मान के लिए जांचा जा सकता है। यदि रिटर्न = कोई नहीं है, यह म्यूट नहीं करता है।
  • क्रमबद्ध () कुछ मामलों में एक वैकल्पिक हल हो सकता है। चूंकि यह मूल के सॉर्ट किए गए संस्करण को लौटाता है, यह आपको अन्य तरीकों से मूल पर काम शुरू करने से पहले एक गैर-उत्परिवर्तित प्रतिलिपि को संग्रहीत करने की अनुमति दे सकता है। हालांकि, यह विकल्प मानता है कि आप मूल तत्वों के क्रम की परवाह नहीं करते हैं (यदि आप करते हैं, तो आपको दूसरा रास्ता खोजने की आवश्यकता है)। इसके विपरीत .sort () मूल को उत्परिवर्तित करता है (जैसा कि कोई उम्मीद कर सकता है)।

गैर-मानक दृष्टिकोण (सहायक के मामले में): इसे एमआईटी लाइसेंस के तहत प्रकाशित जीथब पर मिला:

  • गिथुब रिपॉजिटरी अंडर: टोबुग नाम: पीयरसेंटेंट
  • यह क्या है: उत्परिवर्तन अवांछनीय होने पर कोर डेटा संरचनाओं के स्थान पर उपयोग किया जाने वाला पायथन सस्टेनेबल डेटा स्ट्रक्चर कोड

कस्टम कक्षाओं के लिए, @semicolon चेक करता है कि क्या कोई __hash__फ़ंक्शन है क्योंकि उत्परिवर्तित वस्तुओं में आमतौर पर __hash__()फ़ंक्शन नहीं होना चाहिए ।

यह सब मैं अब के लिए इस विषय पर amassed है। अन्य विचार, सुधार आदि का स्वागत है। धन्यवाद।


3

अंतर के सोचने का एक तरीका:

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


1
यह गलत है। पायथन में सभी असाइनमेंट संदर्भ द्वारा हैं। इसमें कोई नकल शामिल नहीं है।
अगस्तुर

3

सबसे सरल उत्तर:

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

उदाहरण:

>>>x = 5

X द्वारा संदर्भित मान 5 का निर्माण करेगा

x -> 5

>>>y = x

यह कथन 5 x का संदर्भ देगा

x -------------> 5 <----------- y

>>>x = x + y

जैसा कि x एक पूर्णांक (अपरिवर्तनीय प्रकार) का पुनर्निर्माण किया गया है।

बयान में, आरएचएस पर अभिव्यक्ति 10 मूल्य में परिणाम होगा और जब यह एलएचएस (एक्स) को सौंपा जाता है, एक्स 10. का पुनर्निर्माण करेगा। तो अब

एक्स ---------> 10

y ---------> 5


-1

मैंने सभी उत्तरों को नहीं पढ़ा है, लेकिन चयनित उत्तर सही नहीं है और मुझे लगता है कि लेखक के पास एक विचार है जो एक चर को फिर से असाइन करने में सक्षम होने का अर्थ है कि जो भी डेटाटाइप है वह परिवर्तनशील है। बात वह नहीं है। मूल्‍यता को मूल्‍य से गुजरने के बजाय संदर्भ के साथ गुजरना पड़ता है।

कहते हैं कि आपने एक सूची बनाई है

a = [1,2]

यदि आप कहते थे:

b = a
b[1] = 3

भले ही आपने B पर मान पुन: असाइन किया हो, यह भी a पर मान को पुन: असाइन करेगा। इसका कारण जब आप "b = a" असाइन करते हैं। आप मान की एक प्रति के बजाय ऑब्जेक्ट के लिए "संदर्भ" पास कर रहे हैं। यह स्ट्रिंग्स, फ्लोट्स आदि के साथ ऐसा नहीं है। यह सूची, शब्दकोशों और पसंदों को पारस्परिक बनाता है, लेकिन बूलियन, फ़्लोट्स आदि को अपरिवर्तनीय बनाता है।


-1

अपरिवर्तनीय वस्तुओं के लिए, असाइनमेंट मूल्यों की एक नई प्रतिलिपि बनाता है, उदाहरण के लिए।

x=7
y=x
print(x,y)
x=10 # so for immutable objects this creates a new copy so that it doesnot 
#effect the value of y
print(x,y)

परिवर्तनशील वस्तुओं के लिए, असाइनमेंट मानों की एक और प्रतिलिपि नहीं बनाता है। उदाहरण के लिए,

x=[1,2,3,4]
print(x)
y=x #for immutable objects assignment doesn't create new copy 
x[2]=5
print(x,y) # both x&y holds the same list

1
बिलकुल गलत। असाइनमेंट कभी भी कॉपी नहीं बनाता है । कृपया nedbatchelder.com/text/names.html पढ़ें । पहले मामले में, म्यूटेटर पद्धति को कॉल करते समय, x=10बस एक और असाइनमेंट हैx[2] = 5intवस्तुओं में बस उत्परिवर्ती तरीकों की कमी होती है , लेकिन अजगर असाइनमेंट के शब्दार्थ टाइप पर निर्भर नहीं करते हैं
juanpa.arrivillaga

-2

पायथन में, यह जानने का एक आसान तरीका है:

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

    >>> s='asd'
    >>> s is 'asd'
    True
    >>> s=None
    >>> s is None
    True
    >>> s=123
    >>> s is 123
    True

परिवर्त्य:

>>> s={}
>>> s is {}
False
>>> {} is {}
Flase
>>> s=[1,2]
>>> s is [1,2]
False
>>> s=(1,2)
>>> s is (1,2)
False

तथा:

>>> s=abs
>>> s is abs
True

इसलिए मुझे लगता है कि पायथन में अंतर्निहित फ़ंक्शन भी अपरिवर्तनीय है।

लेकिन मैं वास्तव में नहीं समझता कि फ्लोट कैसे काम करता है:

>>> s=12.3
>>> s is 12.3
False
>>> 12.3 is 12.3
True
>>> s == 12.3
True
>>> id(12.3)
140241478380112
>>> id(s)
140241478380256
>>> s=12.3
>>> id(s)
140241478380112
>>> id(12.3)
140241478380256
>>> id(12.3)
140241478380256

यह बहुत अजीब है।


लेकिन यह स्पष्ट रूप से मान्य नहीं है। क्योंकि टुपल्स अपरिवर्तनीय हैं। टाइप करें x = (1, 2)और फिर कोशिश करें और म्यूट करें x, यह संभव नहीं है। एक तरह से मैंने उत्परिवर्तन के लिए जांचने के लिए पाया है hash, यह बिल्टिन वस्तुओं के लिए कम से कम काम करता है। hash(1) hash('a') hash((1, 2)) hash(True)सभी काम करते हैं, और hash([]) hash({}) hash({1, 2})सभी काम नहीं करते हैं।
अर्धवृत्त

@semicolon उपयोगकर्ता-परिभाषित कक्षाओं के लिए तब hash()काम करेगा जब ऑब्जेक्ट एक __hash__()विधि को परिभाषित करता है , भले ही उपयोगकर्ता-परिभाषित कक्षाएं आम तौर पर परिवर्तनशील हों।
अगस्तुर

1
@ उद्घाटनर का अर्थ है हां, लेकिन पायथन में कुछ भी गारंटी नहीं देगा, क्योंकि पायथन की कोई वास्तविक स्थिर टाइपिंग या औपचारिक गारंटी नहीं है। लेकिन hashविधि अभी भी एक बहुत अच्छी है, क्योंकि उत्परिवर्तनीय वस्तुओं में आम तौर पर एक __hash__()विधि नहीं होनी चाहिए , क्योंकि उन्हें एक शब्दकोश में चाबियाँ बनाना सिर्फ खतरनाक है।
अर्धविराम

1
@ दस्तार और अर्धविराम (या यदि वे इसे जानते हैं तो अन्य): __hash __ () समाधान ... क्या एक कस्टम वर्ग के निर्माता को इसे वहां लाने के लिए जोड़ना होगा? यदि ऐसा है, तो नियम है यदि मौजूद है तो वस्तु अपरिवर्तनीय होनी चाहिए; यदि यह मौजूद नहीं है, तो हम यह नहीं बता सकते हैं कि निर्माता ने बंद होने पर बस छोड़ दिया हो सकता है।
TMWP
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.