2010-06-07 10 views
52

... is कीवर्ड जो तारों में समानता के लिए उपयोग किया जा सकता है।पायथन में 'है' कीवर्ड कैसे लागू किया गया है?

>>> s = 'str' 
>>> s is 'str' 
True 
>>> s is 'st' 
False 

मैं दोनों __is__() और __eq__() कोशिश की, लेकिन वे काम नहीं किया।

>>> class MyString: 
... def __init__(self): 
...  self.s = 'string' 
... def __is__(self, s): 
...  return self.s == s 
... 
>>> 
>>> 
>>> m = MyString() 
>>> m is 'ss' 
False 
>>> m is 'string' # <--- Expected to work 
False 
>>> 
>>> class MyString: 
... def __init__(self): 
...  self.s = 'string' 
... def __eq__(self, s): 
...  return self.s == s 
... 
>>> 
>>> m = MyString() 
>>> m is 'ss' 
False 
>>> m is 'string' # <--- Expected to work, but again failed 
False 
>>> 

उत्तर

107

is के साथ परीक्षण स्ट्रिंग केवल स्ट्रिंग इंटर्न किए जाने पर ही काम करता है। जब तक आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं और स्पष्ट रूप से interned स्ट्रिंग्स पर आपको कभीis का उपयोग करना चाहिए। पहचान, नहीं समानता के लिए

is परीक्षण। इसका मतलब है कि पाइथन बस उस ऑब्जेक्ट पते की तुलना करता है जिसमें ऑब्जेक्ट रहता है। is मूल रूप से प्रश्न का उत्तर देता है "क्या मेरे पास एक ही ऑब्जेक्ट के लिए दो नाम हैं?" - ओवरलोडिंग जो कोई समझ नहीं लेगी।

उदाहरण के लिए, ("a" * 100) is ("a" * 100)गलत है। आमतौर पर पाइथन प्रत्येक स्ट्रिंग को एक अलग स्मृति स्थान में लिखता है, इंटर्निंग ज्यादातर स्ट्रिंग अक्षर के लिए होता है।

+8

मैं पिछले कि स्ट्रिंग होना शामिल सके कि वे पर्याप्त कम कर रहे हैं चलाने के समय की गणना की और इनपुट मानों के लिए हो सकता है में मनाया गया है। 'ए' * 100 'ए' * 100 नहीं है; लेकिन 'ए' * 20 "ए" * 20 है। इस बीच 'a'.upper()' a'.upper() नहीं है। ज्योथन, आयरनपीथन, पायपी और अन्य अधिक आक्रामक रूप से प्रशिक्षित हो सकते हैं। संक्षेप में यह कार्यान्वयन निर्भर है। तारों पर 'इंटर्न()' फ़ंक्शन को कॉल करने से एक स्ट्रिंग को बल दिया जाएगा, जैसा कि आप कहते हैं कि समान समकक्ष और पहले इंटर्न() 'डी स्ट्रिंग के समान ऑब्जेक्ट पहचान है। हालांकि, मुझे परीक्षण स्ट्रिंग पहचान के लिए वैध उपयोग केस के बारे में पता नहीं है। (एक तरफ संभव प्रदर्शन)। –

8

is कीवर्ड ऑब्जेक्ट की तुलना करता है (या, तुलनात्मक रूप से तुलना करता है कि दो संदर्भ एक ही वस्तु के हैं)।

मुझे लगता है कि, आपके स्वयं के कार्यान्वयन के लिए कोई तंत्र क्यों नहीं है।

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

>>> a = "string" 
>>> b = "string" 
>>> a is b 
True 
>>> c = "str"+"ing" 
>>> a is c 
True 

आप उम्मीद है कि संदर्भ बनाम एक सरल 'प्रतिलिपि' उदाहरण में डेटा तुलना देख सकते हैं:

>>> a = {"a":1} 
>>> b = a 
>>> c = a.copy() 
>>> a is b 
True 
>>> a is c 
False 
17

is ऑपरेटर id(x) मानों की तुलना करने के लिए बराबर है। id वर्तमान में तुलना के रूप में पॉइंटर्स का उपयोग करने के लिए लागू किया गया है। तो आप is को अधिभारित नहीं कर सकते हैं, और AFAIK आप id को अधिभारित नहीं कर सकते हैं।

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

+1

आप 'id' को अधिभारित कर सकते हैं, लेकिन इस अर्थ में नहीं कि आप शायद इसका मतलब हो। बस 'id = ' करें। – HyperNeutrino

13

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

हालांकि, किसी भी कार्यान्वयन के विवरण के साथ, आपको इस पर भरोसा नहीं करना चाहिए। यदि आप समानता के लिए परीक्षण करना चाहते हैं तो == ऑपरेटर का उपयोग करें। यदि आप वास्तव में ऑब्जेक्ट पहचान के लिए परीक्षण करना चाहते हैं तो is का उपयोग करें --- और मुझे ऐसे मामले के साथ आने के लिए कठोर दबाव डाला जाएगा जहां आपको स्ट्रिंग ऑब्जेक्ट पहचान की परवाह करनी चाहिए। दुर्भाग्यवश आप इस बात पर भरोसा नहीं कर सकते कि उपरोक्त इंटर्निंग की वजह से दो तार किसी भी तरह "जानबूझकर" समान ऑब्जेक्ट संदर्भ हैं।

+0

पायथन में एकमात्र जगह जहां आप पहचान तुलना करना चाहते हैं, सिंगलटन (उदा। कोई नहीं) और सेंटीनेल मानों की तुलना करते समय अद्वितीय होने की आवश्यकता होती है। इसके अलावा, शायद इसके लिए कोई कारण नहीं है। –

+2

@ ली रयान: मैं सहमत हूं। मैंने कभी भी इसे किसी के लिए और विशेष प्रेषणों के लिए कभी भी उपयोग नहीं किया है (आमतौर पर आधार 'ऑब्जेक्ट()' पर कॉल के रूप में)। हालांकि, मुझे यह कहते हुए सहज महसूस नहीं होता कि 'is' ऑपरेटर के लिए कोई अन्य वैध उपयोग नहीं है; सिर्फ इतना नहीं कि मैं सोच सकता हूं। (संभवतः मेरी अपनी अज्ञानता के लिए एक प्रमाण पत्र)। –

5

यदि आप बाइटकोड के साथ गड़बड़ करने से डरते नहीं हैं, तो आप COMPARE_OP के साथ 8 ("is") तर्क के साथ ऑब्जेक्ट पर अपने हुक फ़ंक्शन को कॉल करने के लिए अवरोध और पैच कर सकते हैं। स्टार्ट-इन के लिए dis मॉड्यूल दस्तावेज़ देखें।

और __builtin__.id() को भी अवरुद्ध करना न भूलें यदि कोई a is b के बजाय id(a) == id(b) करेगा।

+1

जानना दिलचस्प है, यह पाइथन के कार्य के साथ गड़बड़ करने की संभावनाओं की पूरी दुनिया है जिसे मैंने कभी नहीं सोचा था। लेकिन यह _ever_ एक अच्छा विचार क्यों होगा? – alexis

+0

मेरी कंपनी में, हमारे पास एक इन-हाउस परीक्षण पुस्तकालय है जिसमें एक संदर्भ सजावट है जो डेटाटाइमटाइम को एक कार्यान्वयन के साथ बदलकर समय को फ्रीज करता है जो हमेशा utcnow() से एक विशिष्ट समय देता है। यदि आप datetime.datetime.utcnow() चलाते हैं और लौटाए गए मान को चुनने का प्रयास करते हैं, तो यह विफल हो जाएगा क्योंकि इसकी कक्षा असंगत है (यह एक और वर्ग होने का नाटक कर रही है)। इस मामले में, 'है' कामों के तरीके को ओवरराइड करना एक समाधान हो सकता है। –

2

स्ट्रिंग वैरिएबल से स्ट्रिंग वैल्यू और दो स्ट्रिंग वैरिएबल की तुलना करने में विफल रहता है जब स्ट्रिंग '-' से शुरू होती है। मेरे अजगर संस्करण 2.6.6

>>> s = '-hi' 
>>> s is '-hi' 
False 
>>> s = '-hi' 
>>> k = '-hi' 
>>> s is k 
False 
>>> '-hi' is '-hi' 
True 
1

आप is ऑपरेटर को ओवरलोड नहीं कर सकता है। आप ओवरलोड करना चाहते हैं == ऑपरेटर है। यह वर्ग में __eq__ विधि को परिभाषित करके किया जा सकता है।

1

आप पहचान तुलना का उपयोग कर रहे हैं। == शायद आप जो चाहते हैं। इसका अपवाद तब होता है जब आप जांचना चाहते हैं कि एक आइटम और दूसरा एक ही वस्तु है और उसी स्मृति स्थिति में हैं। आपके उदाहरणों में, आइटम समान नहीं हैं, क्योंकि एक दूसरे (स्ट्रिंग) की तुलना में एक अलग प्रकार (my_string) का है। इसके अलावा, कुछ वर्ग जैसी कोई चीज नहीं है। पाइथन में __is__ (जब तक, निश्चित रूप से, आप इसे स्वयं वहां नहीं डालते)। यदि वहां था, के साथ वस्तुओं की तुलना स्मृति स्थानों की तुलना करने के लिए विश्वसनीय नहीं होगी।

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

कुछ उपयोगी उदाहरणों और कुछ पाठ यात्रा a document from python.org's mail host "डैनी यू"

या, द्वारा लिखित है कि यदि ऑफ़लाइन है, unlisted pastebin मैं इसे के शरीर से बना का उपयोग कभी कभी भ्रमित अंतर के साथ मदद करने के लिए के लिए ।

मामले में

वे, कुछ 20 या नीले चांद में (नीला चांद एक वास्तविक घटना कर रहे हैं), दोनों नीचे हैं, मैं कोड उदाहरण

### 
>>> my_name = "danny" 
>>> your_name = "ian" 
>>> my_name == your_name 
0    #or False 
### 

### 
>>> my_name[1:3] == your_name[1:3] 
1 #or True 
### 

### 
>>> my_name[1:3] is your_name[1:3] 
0 
### 
0

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

>>> a == b 

True 

करने का मूल्यांकन करने के लिए जा रहा है लेकिन अगर

>>> a is b 

False 

का मूल्यांकन आप शायद

की जाँच करनी चाहिए कर
>>> type(a) 

और

>>> type(b) 

ये अलग-अलग और विफलता के लिए एक कारण हो सकता है।

1

'है' ऑब्जेक्ट पहचान की तुलना करता है जबकि == मूल्यों की तुलना करता है।

उदाहरण:

a=[1,2] 
b=[1,2] 
#a==b returns True 
#a is b returns False 

p=q=[1,2] 
#p==q returns True 
#p is q returns True