स्ट्रिंग्स की तुलना '==' या '' का उपयोग करके कभी-कभी एक अलग परिणाम क्यों होता है?


1146

मुझे एक पायथन प्रोग्राम मिला है जहां दो चर मान पर सेट हैं 'public'। सशर्त अभिव्यक्ति में मेरी तुलना है var1 is var2जो विफल हो जाती है, लेकिन अगर मैं इसे बदल var1 == var2देता हूं तो यह वापस आ जाती है True

अब अगर मैं अपने पायथन इंटरप्रेटर को खोलता हूं और ऐसा ही करता हूं तो "तुलना" होती है, यह सफल होता है।

>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True

मुझे यहां क्या समझ नहीं आ रहा है?



3
यह समस्या तब भी होती है जब आप उदाहरण के माध्यम से कंसोल इनपुट पढ़ते हैं input = raw_input("Decide (y/n): "):। इस स्थिति में "y" का एक इनपुट और if input == 'y':"True" if input is 'y':लौटाएगा जबकि झूठी लौटेगा।
सेमीजॉन मोसेसिंगर

4
यह ब्लॉग किसी भी उत्तर guilload.com/python-string-interning की
Chris_Rands 8

1
जैसा कि @ क्रिस-रिको उल्लेख करता है, मैं यहां बहुत अच्छा स्पष्टीकरण देता हूं। stackoverflow.com/q/15541404/1695680
ThorSummoner

जवाबों:


1532

isपहचान परीक्षण है, ==समानता परीक्षण है। आपके कोड में क्या होता है, इस तरह दुभाषिए का अनुकरण किया जाएगा:

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

तो, कोई आश्चर्य नहीं कि वे समान, सही नहीं हैं?

दूसरे शब्दों में: isहैid(a) == id(b)


17
एह के रूप में ही? बनाम बराबर? योजना में, मिल गया।
jottos

47
या जावा में ==बनाम .equals()। सबसे अच्छी बात यह है कि पायथन ==जावा के अनुरूप नहीं है ==
MatrixFrog

11
@ Крайст: केवल एक ही Noneमूल्य है। तो यह हमेशा एक ही आईडी है।
साइलेंटगॉस्ट

18
यह ओपी के "- सच है" उदाहरण को संबोधित नहीं करता है।
user2864740


569

यहाँ अन्य उत्तर सही हैं: पहचान तुलना के isलिए उपयोग किया जाता है , जबकि समानता तुलना के लिए उपयोग किया जाता है । चूंकि आप जिस चीज की परवाह करते हैं वह समानता है (दो तारों में समान वर्ण होने चाहिए), इस मामले में ऑपरेटर बस गलत है और आपको इसके बजाय उपयोग करना चाहिए ।==is==

isअंतःक्रियात्मक रूप से कार्य करने का कारण यह है कि (अधिकांश) स्ट्रिंग शाब्दिकों को डिफ़ॉल्ट रूप से नजरबंद किया जाता है। विकिपीडिया से:

आंतरिक तार स्ट्रिंग तुलनाओं को गति देते हैं, जो कभी-कभी अनुप्रयोगों (जैसे संकलक और गतिशील प्रोग्रामिंग भाषा रनटाइम्स) में एक प्रदर्शन अड़चन होती है जो स्ट्रिंग कुंजियों के साथ हैश तालिकाओं पर बहुत अधिक भरोसा करते हैं। इंटर्निंग के बिना, यह जांचना कि दो अलग-अलग तार बराबर हैं, दोनों तारों के हर चरित्र की जांच करना शामिल है। यह कई कारणों से धीमा है: यह स्वाभाविक रूप से स्ट्रिंग्स की लंबाई में ओ (एन) है; यह आमतौर पर स्मृति के कई क्षेत्रों से पढ़ता है, जिसमें समय लगता है; और रीडर्स प्रोसेसर कैश को भरता है, जिसका अर्थ है कि अन्य जरूरतों के लिए कम कैश उपलब्ध है। इंटर्न किए गए तारों के साथ, मूल इंटर्न ऑपरेशन के बाद एक साधारण वस्तु पहचान परीक्षण पर्याप्त होता है; यह आमतौर पर एक सूचक समानता परीक्षण के रूप में लागू किया जाता है,

इसलिए, जब आपके पास दो स्ट्रिंग शाब्दिक (शब्द जो आपके प्रोग्राम स्रोत कोड में टाइप किए गए हैं, उद्धरण चिह्नों से घिरे हुए हैं) जो आपके प्रोग्राम में समान मूल्य रखते हैं, तो पायथन कंपाइलर स्वचालित रूप से स्ट्रिंग्स को इंटर्न कर देगा, जिससे दोनों एक ही समय में संग्रहीत होंगे। स्मृति स्थान। (ध्यान दें कि यह हमेशा नहीं होता है, और जब ऐसा होता है तो नियम काफी जटिल होते हैं, इसलिए कृपया उत्पादन कोड में इस व्यवहार पर भरोसा न करें!)

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


6
स्ट्रिंग्स इंटर्न होने पर कोई व्यक्ति नियम के बारे में अधिक पढ़ सकता है?
नॉक्टिस स्काईटॉवर

88
एक पूरी तरह से स्पष्टीकरण के लिए +1। सुनिश्चित नहीं है कि कैसे दूसरे जवाब को यह बताए बिना कि इतने बड़े उठापटक हुए कि क्या हुआ।
That1Guy

4
यह वही है जो मैंने सोचा था कि जब मैंने प्रश्न पढ़ा। स्वीकृत उत्तर कम है फिर भी इसमें तथ्य शामिल हैं, लेकिन यह उत्तर चीजों को बहुत बेहतर बताता है। अच्छा!
S --n Sш Sаӽ

3
@NoctisSkytower Googled एक ही है और इस पाया guilload.com/python-string-interning
xtreak

5
@ naught101: नहीं, शासन के बीच चयन करने के लिए है ==और isक्या की जाँच तरह आप चाहते हैं पर आधारित है। यदि आप स्ट्रिंग्स के बराबर होने के बारे में परवाह करते हैं (यानी समान सामग्री वाले) तो आपको हमेशा उपयोग करना चाहिए ==। यदि आप इस बात की परवाह करते हैं कि क्या कोई दो पायथन नाम एक ही ऑब्जेक्ट उदाहरण के लिए संदर्भित हैं, तो आपको उपयोग करना चाहिए isisयदि आपको ऐसा कोड लिखने की आवश्यकता हो , जो आपकी सामग्री की परवाह किए बिना बहुत सारे भिन्न मानों को संभालता हो, या फिर यदि आप जानते हैं कि केवल एक ही चीज़ है और आप उस चीज़ के बहाने अन्य वस्तुओं को अनदेखा करना चाहते हैं। यदि आप निश्चित नहीं हैं, तो हमेशा चुना ==
डैनियल प्राइडेन

108

isजबकि कीवर्ड वस्तु पहचान के लिए एक परीक्षण है ==एक मूल्य तुलना है।

यदि आप उपयोग करते हैं is, तो परिणाम सही होगा यदि और केवल वस्तु एक ही वस्तु है। हालांकि, ==किसी भी समय सत्य होगा जब वस्तु के मूल्य समान होंगे।


57

नोट करने के लिए एक अंतिम बात, आप sys.internयह सुनिश्चित करने के लिए फ़ंक्शन का उपयोग कर सकते हैं कि आपको उसी स्ट्रिंग का संदर्भ मिल रहा है:

>>> from sys import intern
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

जैसा कि ऊपर बताया गया है, आपको isस्ट्रिंग्स की समानता निर्धारित करने के लिए उपयोग नहीं करना चाहिए । लेकिन यह जानना उपयोगी हो सकता है कि क्या आपके पास उपयोग करने के लिए किसी प्रकार की अजीब आवश्यकता है is

ध्यान दें कि internफ़ंक्शन पायथन 2 पर एक बेसिन हुआ करता था लेकिन sysपायथन 3 में मॉड्यूल में ले जाया गया था ।


43

isपहचान परीक्षण है, ==समानता परीक्षण है। इसका मतलब यह है कि isयह जांचने का एक तरीका है कि क्या दो चीजें समान चीजें हैं, या सिर्फ समकक्ष हैं।

कहें कि आपको एक साधारण personवस्तु मिल गई है । यदि इसे 'जैक' नाम दिया गया है और यह '23' साल पुराना है, तो यह एक और 23yr पुराने जैक के बराबर है, लेकिन यह एक ही व्यक्ति नहीं है।

class Person(object):
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __eq__(self, other):
       return self.name == other.name and self.age == other.age

jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)

jack1 == jack2 #True
jack1 is jack2 #False

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


यदि आप सेट बदलते हैं jack1.age = 99, तो वह नहीं बदलेगा jack2.age। ऐसा इसलिए है क्योंकि वे दो अलग-अलग उदाहरण हैं, इसलिए jack1 is not jack2। हालांकि, वे एक-दूसरे की बराबरी कर सकते हैं jack1 == jack2यदि उनका नाम और उनकी उम्र समान हो। यह स्ट्रिंग्स के लिए अधिक जटिल हो जाता है, क्योंकि पायथन में तार अपरिवर्तनीय हैं, और पायथन अक्सर एक ही उदाहरण का पुन: उपयोग करता है। मुझे यह स्पष्टीकरण पसंद है क्योंकि यह साधारण मामलों (एक सामान्य वस्तु) का उपयोग करता है, बल्कि विशेष मामलों (तार) का।
फ्लिम

37

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

if x is None: 
    # some clauses

यह सुरक्षित है, क्योंकि अशक्त वस्तु (यानी, कोई नहीं) के एक उदाहरण होने की गारंटी है


1
क्या यह सच और गलत के लिए समान है? केवल एक उदाहरण तो मैच होगा?
हैंडीमैनडान

1
@HandyManDan हाँ, वे अजगर 2 और 3 दोनों में
एकल हैं

@kamillitw लेकिन पाइथन 2 में आप फाल्स और ट्रू को रिजेक्ट कर सकते हैं।
मार्टिन पीटर्स

28

यदि आप निश्चित नहीं हैं कि आप क्या कर रहे हैं, तो '==' का उपयोग करें। यदि आपको इसके बारे में थोड़ा और ज्ञान है तो आप 'ऑब्जेक्ट्स' जैसी ज्ञात वस्तुओं के लिए 'is' का उपयोग कर सकते हैं।

अन्यथा आप सोचेंगे कि चीजें काम क्यों नहीं करती हैं और ऐसा क्यों होता है:

>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False

मुझे यकीन भी नहीं है कि अगर कुछ चीजों को अलग-अलग अजगर संस्करणों / कार्यान्वयनों के बीच रहने की गारंटी दी जाती है।


1
दिलचस्प उदाहरण दिखाते हैं कि कैसे पुन: असाइन करने वाली चींटियां इस स्थिति को ट्रिगर करती हैं। यह असफल क्यों हुआ? यह इंटर्न-इंग के कारण है या कुछ और है?
पॉल

ऐसा लगता है कि दुभाषिया कार्यान्वयन के कारण झूठे होने का कारण बनता है: stackoverflow.com/questions/132988/…
पॉल


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

20

अजगर के साथ मेरे सीमित अनुभव से, isदो वस्तुओं की तुलना करने के लिए उपयोग किया जाता है , यह देखने के लिए कि क्या वे एक ही वस्तु के समान दो भिन्न वस्तुओं के विपरीत हैं। ==यह निर्धारित करने के लिए उपयोग किया जाता है कि मान समान हैं या नहीं।

यहाँ एक अच्छा उदाहरण है:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

s1 एक यूनिकोड स्ट्रिंग है, और s2 एक सामान्य स्ट्रिंग है। वे समान प्रकार नहीं हैं, लेकिन समान मूल्य हैं।


17

मुझे लगता है कि यह इस तथ्य के साथ करना है कि, जब 'है' तुलना का मूल्यांकन असत्य से किया जाता है, तो दो अलग-अलग वस्तुओं का उपयोग किया जाता है। यदि यह सत्य का मूल्यांकन करता है, तो इसका मतलब है कि आंतरिक रूप से यह एक ही सटीक वस्तु का उपयोग कर रहा है और एक नया नहीं बना रहा है, संभवतः क्योंकि आपने उन्हें 2 या इतने सेकंड के एक अंश के भीतर बनाया है और क्योंकि इसके बीच एक बड़ा समय अंतराल नहीं है और यह अनुकूलित है और एक ही वस्तु का उपयोग करता है।

यही कारण है कि आपको एक स्ट्रिंग ऑब्जेक्ट के मूल्य की तुलना करने के लिए समानता ऑपरेटर का उपयोग करना चाहिए ==, न isकि।

>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>> 

इस उदाहरण में, मैंने s2 बनाया, जो पहले 'एक' के बराबर एक अलग स्ट्रिंग ऑब्जेक्ट था, लेकिन यह उसी वस्तु के रूप में नहीं है s, क्योंकि दुभाषिया ने उसी ऑब्जेक्ट का उपयोग नहीं किया, जैसा कि मैंने शुरू में इसे 'एक' के लिए असाइन नहीं किया था, अगर मेरे पास होता तो मैं उन्हें एक ही वस्तु बना देता।


3
.replace()इस संदर्भ में एक उदाहरण के रूप में उपयोग करना संभवतः सबसे अच्छा नहीं है, हालांकि, इसके शब्दार्थ भ्रामक हो सकते हैं। s2 = s2.replace()जाएगा हमेशा एक बनाने के नए स्ट्रिंग वस्तु, के लिए नए स्ट्रिंग वस्तु आवंटित s2, और फिर उस स्ट्रिंग वस्तु के निपटान s2के लिए बात करने के लिए इस्तेमाल किया। तो अगर आपने किया तो भी आपको s = s.replace('one', 'one')एक नया स्ट्रिंग ऑब्जेक्ट मिलेगा।
डैनियल प्राइडेन

13

मेरा मानना ​​है कि इसे "इंटर्न" स्ट्रिंग्स के रूप में जाना जाता है। पाइथन ऐसा करता है, तो जावा करता है, और इसलिए अनुकूलित मोड में संकलन करते समय C और C ++ करते हैं।

यदि आप दो समान वस्तुओं का निर्माण करके मेमोरी को बर्बाद करने के बजाय दो समान तारों का उपयोग करते हैं, तो समान सामग्री वाले सभी आंतरिक तार एक ही मेमोरी को इंगित करते हैं।

पायथन में यह परिणाम "है" ऑपरेटर रिटर्निंग ट्रू क्योंकि एक ही सामग्री के साथ दो तार एक ही स्ट्रिंग ऑब्जेक्ट पर इंगित कर रहे हैं। यह जावा और सी में भी होगा।

यह केवल स्मृति बचत के लिए उपयोगी है। आप स्ट्रिंग समानता के लिए परीक्षण करने के लिए उस पर भरोसा नहीं कर सकते, क्योंकि विभिन्न दुभाषिए और संकलक और जेआईटी इंजन हमेशा ऐसा नहीं कर सकते हैं।


12

मैं इस सवाल का जवाब दे रहा हूं, हालांकि यह सवाल पुराना है क्योंकि ऊपर दिए गए कोई भी उत्तर भाषा के संदर्भ में नहीं है

दरअसल ऑपरेटर पहचान के लिए जाँच करता है और == ऑपरेटर चेक समानता के लिए,

भाषा संदर्भ से:

प्रकार वस्तु व्यवहार के लगभग सभी पहलुओं को प्रभावित करते हैं। यहां तक ​​कि वस्तु पहचान का महत्व कुछ अर्थों में प्रभावित होता है: अपरिवर्तनीय प्रकारों के लिए, नए मूल्यों की गणना करने वाले संचालन वास्तव में किसी भी मौजूदा वस्तु के संदर्भ को उसी प्रकार और मूल्य के साथ वापस कर सकते हैं, जबकि उत्परिवर्तित वस्तुओं के लिए यह अनुमति नहीं है । जैसे, = 1 के बाद; बी = 1, ए और बी मूल्य के साथ एक ही वस्तु को संदर्भित कर सकते हैं या नहीं कर सकते हैं, कार्यान्वयन के आधार पर, लेकिन c = [] के बाद; d = [], c और d दो अलग, अद्वितीय, नव निर्मित खाली सूचियों को संदर्भित करने की गारंटी है। (ध्यान दें कि c = d = [] c और d दोनों को एक ही वस्तु प्रदान करता है।)

इसलिए उपरोक्त कथन से हम यह अनुमान लगा सकते हैं कि जो अपरिवर्तनीय प्रकार है वह "" है "के साथ जांचे जाने पर विफल हो सकता है और जब" के साथ जांच की जाती है तो सफल हो सकता है "

वही int, tuple के लिए लागू होता है जो अपरिवर्तनीय प्रकार भी होते हैं


8

==ऑपरेटर परीक्षण मूल्य तुल्यता। isऑपरेटर परीक्षण वस्तु पहचान, चाहे दो अजगर परीक्षण वास्तव में एक ही वस्तु (यानी, स्मृति में एक ही पते पर लाइव) कर रहे हैं।

>>> a = 'banana'
>>> b = 'banana'
>>> a is b 
True

इस उदाहरण में, पायथन ने केवल एक स्ट्रिंग ऑब्जेक्ट बनाया, और दोनों aऔर bइसे संदर्भित करता है। इसका कारण यह है कि पायथन आंतरिक रूप से कैश करता है और अनुकूलन के रूप में कुछ तारों का पुन: उपयोग करता है, वास्तव में स्मृति में एक स्ट्रिंग 'केला' है, जिसे ए और बी द्वारा साझा किया गया है; सामान्य व्यवहार को ट्रिगर करने के लिए, आपको लंबे तार का उपयोग करने की आवश्यकता है:

>>> a = 'a longer banana'
>>> b = 'a longer banana'
>>> a == b, a is b
(True, False)

जब आप दो सूची बनाते हैं, तो आपको दो ऑब्जेक्ट मिलते हैं:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False

इस मामले में हम कहेंगे कि दो सूचियाँ समान हैं, क्योंकि उनके समान तत्व हैं, लेकिन समान नहीं हैं, क्योंकि वे एक ही वस्तु नहीं हैं। यदि दो वस्तुएँ समान हैं, तो वे भी समतुल्य हैं, लेकिन यदि वे समतुल्य हैं, तो वे समान नहीं हैं।

अगर a किसी ऑब्जेक्ट को संदर्भित करता है और आप असाइन करते हैं b = a, तो दोनों चर एक ही ऑब्जेक्ट को संदर्भित करते हैं:

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True

7

isस्मृति स्थान की तुलना करेगा। इसका उपयोग वस्तु-स्तर की तुलना के लिए किया जाता है।

==कार्यक्रम में चर की तुलना करेंगे। इसका उपयोग मूल्य स्तर पर जाँच के लिए किया जाता है।

is पता स्तर तुल्यता के लिए जाँच

== मूल्य स्तर तुल्यता के लिए जाँच


3

isपहचान परीक्षण है, ==समानता परीक्षण है ( पायथन डॉक्यूमेंटेशन देखें )।

ज्यादातर मामलों में, अगर a is b, तब a == b। लेकिन अपवाद हैं, उदाहरण के लिए:

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

तो, आप केवल isपहचान परीक्षणों के लिए उपयोग कर सकते हैं , कभी भी समानता परीक्षण नहीं कर सकते ।

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