2012-01-29 11 views
6

नोट करता है: अजगरक्या `सुपर()` में `__new__`

import weakref 

class CarModel: 
    _models = weakref.WeakValueDictionary() 

    def __new__(cls, model_name, *args, **kwargs): 
     model = cls._models.get(model_name) 
     if not model: 
      model = super().__new__(cls) 
      cls._models[model_name] = model  
     return model 

    def __init__(self, model_name, air=False): 
     if not hasattr(self, "initted"): 
      self.model_name = model_name 
      self.air = air 
      self.initted=True 

प्रश्न 1 के साथ एक फ्लाईवेट कार्यान्वयन के भाग>super() क्या मतलब है? क्या इसका मतलब CarModel का मूल वर्ग है?

प्रश्न 2> मुझे यह समझने में भी कठिनाई है कि फ़ंक्शन __new__ फ़ंक्शन कैसे काम करता है? विशेष रूप से, निम्नलिखित पंक्ति।

model = super().__new__(cls) 

__new__ के लिए विवरण:

निर्माता समारोह __new__ कहा जाता है के रूप में __init__ करने का विरोध किया है, और ठीक एक तर्क स्वीकार करता है, उस वर्ग का निर्माण किया जा रहा है से पहले वस्तु है (यह कहा जाता है निर्मित, इसलिए कोई स्वयं तर्क नहीं है)। इसे नव निर्मित वस्तु को भी वापस करना होगा।

+1

@Ben, [दस्तावेज़] (http://docs.python.org/py3k/reference/datamodel] पर आधारित है।एचटीएमएल # ऑब्जेक्ट्स-वैल्यू-एंड-टाइप), '__new __() '' cls' का एक उदाहरण देता है। क्यों कोड 'मॉडल = सुपर() .__ नया __ (सीएलएस) ' ओपी में 'cls' का उदाहरण बना सकता है? कारमोडेल की सुपर क्लास कैसे जानता है कि इसके सबक्लास का उदाहरण कैसे बनाया जाए? – q0987

+2

यह अपने आप पर एक महान SO सवाल होगा (यदि यह पहले से ही नहीं पूछा गया है)। संक्षिप्त जवाब यह है कि आप इसे 'क्लास' पैरामीटर के साथ वर्तमान कक्षा पास कर रहे हैं। आखिरकार 'ऑब्जेक्ट .__ new__' पर वापस जाने के बिना बिल्कुल नया उदाहरण बनाने का कोई तरीका नहीं है, क्योंकि पाइथन के पास "आवंट आवंटित करने" के लिए कोई निर्देश नहीं है। लेकिन 'ऑब्जेक्ट .__ new__' यह कक्षा के एक उदाहरण को बनाने के लिए जानता है (जो ऑब्जेक्ट' का एक उदाहरण भी होगा, क्योंकि सब कुछ 'ऑब्जेक्ट' का उदाहरण है)। – Ben

उत्तर

1

super() सुपरक्लास (यानी मूल वर्ग जिसे आप उपclassing कर रहे हैं) के संदर्भ में उपयोग किया जाता है।

__new__ एक विधि है जिसे कक्षा के एक नए उदाहरण को परिभाषित करने के लिए बुलाया जाता है, यदि यह परिभाषित किया गया है।

+0

'सुपर (कक्षा 1, कक्षा 2) 'में,' super'' class1' और 'class2' का उपयोग कैसे करता है? – Adrian

1

मेरा मानना ​​है कि आप पाइथन 3 का उपयोग कर रहे हैं, जहां सुपर को उसी कक्षा के नाम के साथ प्रदान करने की आवश्यकता नहीं है। सुपर वर्तमान कक्षा के बेस क्लास को संदर्भित करता है और सही बेस क्लास से विधि का आह्वान करने के लिए उचित Method Resolution Order करता है। __new__ वह विधि है जिसे एक उदाहरण बनाने के लिए बुलाया जाता है। यह first step in the instance creation है।

+0

'सुपर (कक्षा 1, कक्षा 2) 'में,' super'' class1' और 'class2' का उपयोग कैसे करता है? – Adrian

11

super() साथ शुरू करने के लिए अपने आप में बस super(A, B), जहां A वर्ग जिसमें कोड होता है के लिए आशुलिपि है, और B जिसमें कोड होता है कार्य करने के लिए पहला तर्क है, इसलिए आपके विशेष मामले में, super().__new__(cls)super(CarModel, cls).__new__(cls) तक फैलता है।

बदले में, super(T, O) एक "सुपर ऑब्जेक्ट" देता है। यह समझने के लिए कि एक सुपर ऑब्जेक्ट क्या करता है, आपको समझने की आवश्यकता है कि पाइथन में उदाहरण और कक्षाओं पर विशेषता संदर्भ कैसे हैं।

मान लिया जाये कि कोई __getattr__ या __getattribute__ तरीकों शामिल कर रहे हैं, एक वस्तु O पर विशेषता A संदर्भित (अर्थात, O.A या getattr(O, "A") का मूल्यांकन) के लिए निम्न चरण होकर गुज़रता है:

  1. तो "A"O के उदाहरण में परिभाषित किया गया है dict (O.__dict__), तो उस निर्देश पर मूल्य सीधे लौटा दिया जाता है, ठीक उसी तरह।
  2. अन्यथा, O के विधि संकल्प आदेश में से प्रत्येक कक्षा बदले में चेक की जाती है, "A" उनके प्रत्येक डिब्बे में देखती है। यदि पाया जाता है, तो मान D पर कॉल करें।
  3. यदि D बदले में, __get__ को परिभाषित नहीं करता है, तो यह वापस लौटाया जाता है।यदि ऐसा होता है, तो D को "वर्णक" के रूप में जाना जाता है, और इसकी __get__ विधि को पहले तर्क के रूप में O और दूसरे तर्क के रूप में type(O) कहा जाता है।

एक वर्ग पर एक विशेषता संदर्भ में, एक ही काम करता है के बारे में उदाहरण के लिए वर्ग संदर्भ जा रहा है प्रतिस्थापन, निम्नलिखित अंतर के साथ:

  • चरण 1 लागू नहीं होता।
  • __get__ विधि को पहले तर्क के रूप में None के साथ बुलाया जाता है, और कक्षा को दूसरे के रूप में संदर्भित किया जाता है।

पायथन उदाहरण विधियों, कक्षा विधियों, स्थिर विधियों और गुणों जैसी चीजों को लागू करने के लिए वर्णनकर्ताओं का उपयोग करता है।

super(T, O) के साथ बनाई गई एक सुपर वस्तु है, तो, एक (बिल्ट-इन) उस पर संदर्भ एक __getattribute__ विधि है जो हर पर कहा जाता है के साथ वस्तु विशेषता है, और केवल निम्नलिखित टी वर्गों के dicts में विशेषता ऊपर लग रहा हैO के एमआरओ में। इसके बाद जो मूल्य मिलता है, वह सामान्य रूप से __get__ पर कॉल करता है।

प्रक्रिया थोड़ा जटिल है, इसलिए एक उदाहरण के रूप में, यह आपके विशिष्ट मामले पर कैसे काम करेगा। चूंकि CarModel को परिभाषित किया गया है, इसलिए इसका एमआरओ [CarModel, object] है।

  1. super().__new__(cls) ऊपर वर्णित अनुसार super(CarModel, cls).__new__(cls) तक फैला है।
  2. super(CarModel, cls) का मूल्यांकन एक सुपर ऑब्जेक्ट S उत्पन्न करने के लिए किया जाता है।
  3. पायथन "__new__" पर S पर गुण प्राप्त करता है (पाइथन कोड में getattr(S, "__new__") पर कॉल करने के बराबर)।
  4. S के बाद से CarModel वर्ग पर बनाया गया था, यह CarModel के एमआरओ में CarModel निम्नलिखित वर्गों समझता है, और object वर्ग के ही dict में "__new__" पाता है। इसका मूल्य, एक स्थिर विधि, __get__ विधि है, जिसे None और cls तर्कों के साथ बुलाया जाता है। चूंकि __new__ एक स्थैतिक विधि है, इसकी __get__ विधि केवल कार्य को लौटती है, जैसा कि यह है, असम्बद्ध है। इसलिए, super(CarModel, cls).__new__ ठीक है object.__new__ जैसा ही है।
  5. अंतिम चरण में प्राप्त (अर्थात, object.__new__ है) समारोह cls तर्क है, जहां cls शायद CarModel, अंत में CarModel वर्ग का एक नया उदाहरण है के साथ कहा जाता है।

मुझे आशा है कि यह सब समझ में आता है।

(पूर्णता के लिए के लिए, यह उल्लेखनीय है कि object वर्ग पर वास्तविक __new__ समारोह वास्तव में एक स्थिर तरीका नहीं है, लेकिन एक विशेष समारोह में निर्मित बस सभी में कोई __get__ विधि है, लेकिन जब से __get__ स्थैतिक विधियों पर विधि केवल उस फ़ंक्शन को वापस लौटाएं, जिसका प्रभाव उनके साथ परिभाषित किया गया था, प्रभाव समान है।)

+0

'सुपर (कक्षा 1, कक्षा 2) 'में,' super'' class1' और 'class2' का उपयोग कैसे करता है? – Adrian

+0

@ एड्रियन: मुझे नहीं लगता कि मैं आपके प्रश्न को समझता हूं, क्योंकि ऐसा लगता है कि पूरा जवाब समझाने के लिए क्या है। क्या इसके बारे में कोई विशेष हिस्सा है? – Dolda2000

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