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




string comparison (10)

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

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

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

अब अगर मैं अपना पायथन दुभाषिया खोलता हूं और वही "तुलना" करता हूं, तो यह सफल होता है।

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

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


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

>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

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

ध्यान दें कि पाइथन 3 के लिए मॉड्यूल sys में होने के लिए इंटर्न फ़ंक्शन एक अंतर्निहित फ़ंक्शन होने से स्थानांतरित हो गया है।


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

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

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

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


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

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

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

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


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

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

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

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


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

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

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

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


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

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

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

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



स्मृति स्थान की तुलना करेगा। यह ऑब्जेक्ट-स्तरीय तुलना के लिए प्रयोग किया जाता है।

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

पता स्तर समकक्ष के लिए जांच है

== मूल्य स्तर समकक्षता के लिए जांच करता है


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

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

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

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

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




comparison