2011-01-09 10 views
12

Python documentation about the is operator का कहना है:एक विधि खुद के समान क्यों नहीं है?

ऑपरेटरों is और वस्तु पहचान के लिए is not परीक्षण: x is y सच है अगर और केवल तभी x और y एक ही वस्तु है। x is not y उलटा सच्चाई मूल्य उत्पन्न करता है।

की कि कोशिश करते हैं:

>>> def m(): 
... pass 
... 
>>> m is m 
True 

Python documentation also says:

कारण स्वत: कचरा-संग्रह, मुक्त सूचियों, और वर्णनकर्ता के गतिशील स्वभाव के हैं, तो आप उचित रूप में देख सकते हैं is ऑपरेटर के कुछ उपयोगों में असामान्य व्यवहार, जैसे comp उदाहरण विधियों, या स्थिरांक के बीच arisons। अधिक जानकारी के लिए अपने दस्तावेज़ीकरण की जांच करें।

>>> class C: 
... def m(): 
...  pass 
... 
>>> C.m is C.m 
False 

मैं और अधिक स्पष्टीकरण के लिए खोज की है, लेकिन मैं किसी भी खोजने के लिए सक्षम नहीं था।

C.m is C.m क्यों झूठा है?

मैं पायथन 2.x का उपयोग कर रहा हूं। जैसा कि नीचे दिए गए उत्तरों में उल्लेख किया गया है, पायथन 3.x C.m is C.m में सत्य है।

उत्तर

17

जब आप किसी फ़ंक्शन के उदाहरण की विशेषता के लिए पूछते हैं, तो आपको बाध्य विधि मिलती है: एक कॉल करने योग्य ऑब्जेक्ट जो कक्षा में परिभाषित फ़ंक्शन को लपेटता है और उदाहरण को पहले तर्क के रूप में पास करता है। अजगर 2.x में, जब आप एक वर्ग के एक विशेषता है जो एक समारोह में आप प्राप्त एक समान प्रॉक्सी वस्तु एक अनबाउंड विधि कहा जाता है के लिए पूछना:

>>> class A: m = lambda: None 
... 
>>> A.m 
<unbound method A.<lambda>> 

जब आप इसे के लिए पूछने के इस विशेष वस्तु बन जाता है, और स्पष्ट रूप से कहीं भी कैश नहीं किया। इसका मतलब है कि आप

>>> A.m is A.m 
False 

आप दो अलग अनबाउंड विधि वस्तुओं बनाने और उन्हें पहचान के लिए परीक्षण कर रहे हैं करते हैं जब।

सूचना है कि

>>> x = A.m 
>>> x is x 
True 

और

>>> A.m.im_func is A.m.im_func 
True 

काम ठीक। (im_func मूल कार्य जो अबाध विधि वस्तु लपेटकर जाता है।)

अजगर 3.x में, संयोग से, C.m is C.m यह सच है, क्योंकि (कुछ व्यर्थ) अनबाउंड विधि प्रॉक्सी वस्तुओं पूरी तरह से हटा दिया गया है और तुम सिर्फ मूल मिल फ़ंक्शन जिसे आपने परिभाषित किया है।


यह अजगर में विशेषता देखने की बहुत गतिशील प्रकृति के केवल एक उदाहरण है: जब आप एक वस्तु की एक विशेषता के लिए पूछना है, यह है कि विशेषता के मान की गणना करने के मनमाने ढंग से अजगर को चलाने के लिए संभव है। यहाँ एक और उदाहरण है, जहां अपने परीक्षण में विफल रहता है, जिसमें यह बहुत स्पष्ट है क्यों:

>>> class ChangingAttribute(object): 
...  @property 
...  def n(self): 
...    self._n += 1 
...    return self._n 
... 
...  def __init__(self): 
...    self._n = 0 
... 
>>> foo = ChangingAttribute() 
>>> foo.n 
1 
>>> foo.n 
2 
>>> foo.n 
3 
>>> foo.n is foo.n 
False 
>>> foo.n 
6 
+0

पूर्णता के लिए, [वर्णनकर्ता] (http://docs.python.org/reference/datamodel.html#invoking-descriptors) इस गतिशील विशेषता लुकअप करें। यह सुपरक्लास को भी विशेषता पहुंच को रोकता है। –

+0

हां, हालांकि आप '__getattr__' का उपयोग करके एक उदाहरण भी लिख सकते हैं। – katrielalex

4

क्योंकि सेमी() वर्ग सी के एक स्थिर तरीका नहीं है:

इस तरह यह प्रयास करें:

class C: 
    @staticmethod 
    def m(): 
     pass 

print C.m is C.m 
# True 

c = C() 
print c.m is C.m 
# True 

क्योंकि स्थिर विधियां कक्षा चर की तरह हैं, हम केवल उनके लिए एक संदर्भ चाहते हैं ताकि यदि हम अपना बाध्य मान बदलते हैं तो यह परिवर्तन सभी वर्ग और इस वर्ग के उदाहरण में स्वचालित होना चाहिए।

दूसरी ओर, अपने उदाहरण में, C.m नहीं एक स्थिर विधि तो अजगर धारणा है कि यह एक गैर स्थिर विधि की तरह व्यवहार किया जाना चाहिए बनाता है, इसलिए जब भी आप C.m कहते हैं, यह एक नया उदाहरण वापस आ जाएगी है:

class C: 
    def m(): 
     pass 

a = C.m 
b = C.m 

print id(a), id(b) 
# 43811616, 43355984 
print a is b 
# False 

एनबी: स्थैतिक विधियां कक्षा विधियों की तरह नहीं हैं!

6

मुझे लगता है कि आप पाइथन 2 का उपयोग कर रहे हैं? पायथन 3, C.m is C.m (लेकिन C().m is C().m अभी भी झूठा है) में। यदि आप REPL पर केवल C.m दर्ज करते हैं, तो मुझे लगता है कि आप <UnboundMethod... > जैसे कुछ देखते हैं। isinstance(self, cls) को छोड़कर, एक UnboundMethod wrapper बहुत कम करता है। (इसके लिए एक रैपर बनाने के लिए सुंदर व्यर्थ लगता है? यह है, इसलिए इसे पायथन 3 - C.m में गिरा दिया गया था)। जब भी विधि का उपयोग किया जाता है तो एक ताजा रैपर आवृत्ति मांग पर बनाई जाती है - C.m एक बनाता है, दूसरा C.m दूसरा बनाता है। चूंकि वे अलग-अलग उदाहरण हैं, C.m is not C.m

निकटता से संबंधित बाध्य विधियां हैं, जो आपको f = obj.method; f(*args) करने की अनुमति देती हैं लेकिन instance.method is not instance.method भी होती हैं। Instanciation पर, वर्ग में परिभाषित सभी कार्यों (पढ़ें: पाठ्यक्रम के बंदरगाह को छोड़कर सभी विधियों) उदाहरण के गुण बन जाते हैं। जब आप उन्हें एक्सेस करते हैं, तो आपको सादे फ़ंक्शन के चारों ओर एक रैपर (बाध्य विधि) का एक नया उदाहरण मिलता है। यह रैपर उदाहरण (self) को याद करता है और जब (arg1, arg2, ..., argN) के साथ बुलाया जाता है तो यह केवल फ़ंक्शन पर हाथ रखता है - self के साथ पहले तर्क के रूप में जोड़ा जाता है। आप आमतौर पर ध्यान नहीं देते क्योंकि आप तुरंत विधि को कॉल करते हैं - लेकिन यह self को भाषा-स्तर की चालबाजी का उपयोग किए बिना पूरी तरह से गुजरने की अनुमति देता है।

अधिक जानकारी और, अच्छी तरह से, इतिहास के लिए the history of Python देखें।

संबंधित मुद्दे