2015-11-25 5 views
12

यदि हमारे पास x = type(a) और x == y है, तो क्या यह आवश्यक है कि x is y?क्लासोबजेक्ट सिंगलेट्स हैं?

यहाँ प्रति एक है, लेकिन यह एक धोखा है:

>>> class BrokenEq(type): 
...  def __eq__(cls, other): 
...   return True 
...  
>>> class A(metaclass=BrokenEq): 
...  pass 
... 
>>> a = A() 
>>> x = type(a) 
>>> x == A, x is A 
(True, True) 
>>> x == BrokenEq, x is BrokenEq 
(True, False) 

और मैं इस तरह प्रति एक नहीं बना सका:

>>> A1 = type('A',(), {}) 
>>> A2 = type('A',(), {}) 
>>> a = A1() 
>>> x = type(a) 
>>> x == A1, x is A1 
(True, True) 
>>> x == A2, x is A2 
(False, False) 

मेरे सवाल का स्पष्ट करने के लिए - समानता अधिभावी के बिना ऑपरेटर कुछ पागल करने के लिए, क्या कक्षा के लिए दो अलग-अलग मेमोरी स्थानों पर मौजूद होना संभव है या क्या आयात प्रणाली इसे किसी भी तरह से रोकती है?

यदि हां, तो हम इस व्यवहार को कैसे प्रदर्शित कर सकते हैं - उदाहरण के लिए, reload या __import__ के साथ अजीब चीजें कर रहे हैं?

यदि नहीं, तो क्या यह भाषा या कहीं भी दस्तावेज की गारंटी है?


उपसंहार:

# thing.py 
class A: 
    pass 

अंत में, यह है कि क्या मेरे लिए वास्तविक व्यवहार स्पष्ट किया है (और यह Blckknght जवाब में दावा समर्थन है)

>>> import sys 
>>> from thing import A 
>>> a = A() 
>>> isinstance(a, A), type(a) == A, type(a) is A 
(True, True, True) 
>>> del sys.modules['thing'] 
>>> from thing import A 
>>> isinstance(a, A), type(a) == A, type(a) is A 
(False, False, False) 

इसलिए, भले ही कोड importlib.reload का उपयोग कक्षा पहचान द्वारा टाइपिंग प्रकार को तोड़ सकता है, यह भी isinstance तोड़ देगा।

+1

दिलचस्प सवाल! मुझे लगता है कि उन्हें होना चाहिए, बस इसलिए कि किसी दिए गए प्रकार की वस्तु संभवतया केवल एक ही तरीके से बनाई जाएगी। क्या मैं ऐसा कुछ कह सकता हूं? अभी नहीं। –

+0

चूंकि सब कुछ अजगर में एक वस्तु है, इसलिए कक्षाएं उनके मेटाक्लास के "बस" उदाहरण हैं - हमारे पास "समान" कक्षा के अन्य उदाहरण क्यों नहीं हो सकते? हालांकि, मैं एक ऐसा उदाहरण ढूंढने में असफल रहा हूं जहां कक्षा को आयात करना या अन्यथा कक्षा में नाम बाध्य करना एक ही वस्तु के लिए एक और संदर्भ नहीं मिलता है। – wim

+0

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

उत्तर

5

नहीं, मेटाक्लास __eq__ विधियों के साथ गड़बड़ करने के अलावा, दो वर्ग वस्तुओं को बनाने के लिए कोई रास्ता नहीं है, जो समान होने के बराबर तुलना करते हैं।

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

विभिन्न मेमोरी स्थानों पर एक ही कक्षा में दो अलग-अलग रिफ्रेंस प्राप्त करने के लिए, यह पाइथन के ऑब्जेक्ट अर्थशास्त्र के कारण वास्तव में संभव नहीं है। ऑब्जेक्ट का मेमोरी लोकेशन इसकी पहचान (कम से कम cpython में) है। समान सामग्री वाला एक और वर्ग कहीं और मौजूद हो सकता है, लेकिन आपके A1 और A2 उदाहरण की तरह, यह सभी पायथन तर्क द्वारा एक अलग वस्तु के रूप में देखा जा रहा है।

+0

हाय! तो जवाब ऐसा प्रतीत होता है: नहीं, वे सिंगलटन नहीं हैं (जिसका मतलब होगा कि क्लासोबजेक्ट्स के निर्माण को रोकना होगा)। लेकिन उनके डिफ़ॉल्ट '__eq__', जिन्हें वे 'ऑब्जेक्ट' से प्राप्त करते हैं, गूंगा है - भले ही वर्ग समान स्रोत कोड से उत्पन्न होते हैं, वे बराबर तुलना नहीं करते हैं। क्या यह सही है? – wim

+0

ठीक है, क्लास ऑब्जेक्ट्स कुछ सिंगलटन क्लास के उदाहरण नहीं हैं, वे 'टाइप' मेटाटाइप के सामान्य उदाहरण हैं। कॉलिंग 'टाइप (ओबीजे)' एक नया प्रकार नहीं बनाता है, यह सिर्फ 'obj' (obj .__ class__' से) के प्रकार को देखता है और उस पूर्व-एक्सिसिटिंग ऑब्जेक्ट का संदर्भ देता है। – Blckknght

5

मुझे == प्रकारों के लिए कैसे काम करता है, इस बारे में कोई जानकारी नहीं है, लेकिन यह निश्चित रूप से पहचान द्वारा काम करता है।आप देख सकते हैं कि CPython 2.7 implementation एक सूचक तुलना है:

static PyObject* 
type_richcompare(PyObject *v, PyObject *w, int op) 
{ 
    ... 

    /* Compare addresses */ 
    vv = (Py_uintptr_t)v; 
    ww = (Py_uintptr_t)w; 
    switch (op) { 
    ... 
    case Py_EQ: c = vv == ww; break; 

CPython 3.5 में, type अपनी ही tp_richcompare लागू नहीं होता है, तो यह object से डिफ़ॉल्ट समानता तुलना है, जो एक सूचक तुलना है विरासत:

PyTypeObject PyType_Type = { 
    ... 
    0,           /* tp_richcompare */ 
संबंधित मुद्दे