python - समस - पायथन: कक्षा और उदाहरण विशेषताओं के बीच अंतर




संविधानवाद के प्रमुख तत्वों की विवेचना कीजिए (4)

अंतर यह है कि वर्ग पर विशेषता सभी मामलों से साझा की जाती है। एक उदाहरण पर विशेषता उस उदाहरण के लिए अद्वितीय है।

यदि सी ++ से आ रहा है, तो वर्ग पर गुण स्थिर सदस्य चर की तरह अधिक हैं।

क्या इसमें कोई सार्थक भेद है:

class A(object):
    foo = 5   # some default value

बनाम

class B(object):
    def __init__(self, foo=5):
        self.foo = foo

यदि आप बहुत सारे उदाहरण बना रहे हैं, तो क्या दो शैलियों के लिए प्रदर्शन या अंतरिक्ष आवश्यकताओं में कोई अंतर है? जब आप कोड पढ़ते हैं, तो क्या आप दो शैलियों का अर्थ काफी अलग मानते हैं?


एक और स्थिति है।

कक्षा और उदाहरण विशेषता वर्णनकर्ता है।

# -*- encoding: utf-8 -*-


class RevealAccess(object):
    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        return self.val


class Base(object):
    attr_1 = RevealAccess(10, 'var "x"')

    def __init__(self):
        self.attr_2 = RevealAccess(10, 'var "x"')


def main():
    b = Base()
    print("Access to class attribute, return: ", Base.attr_1)
    print("Access to instance attribute, return: ", b.attr_2)

if __name__ == '__main__':
    main()

उपरोक्त आउटपुट होगा:

('Access to class attribute, return: ', 10)
('Access to instance attribute, return: ', <__main__.RevealAccess object at 0x10184eb50>)

कक्षा या उदाहरण के माध्यम से उसी प्रकार का इंस्टेंस एक्सेस अलग-अलग परिणाम देता है!

और मुझे c.PyObject_GenericGetAttr परिभाषा , और एक महान post

समझाना

यदि विशेषता कक्षाओं के शब्दकोश में पाया जाता है जो बनाते हैं। ऑब्जेक्ट्स एमआरओ, फिर यह देखने के लिए जांचें कि क्या विशेषता डेटा डिस्क्रिप्टर को इंगित करती है (जो कि __get__ और __set__ विधियों दोनों को लागू करने वाली कक्षा नहीं है)। यदि ऐसा होता है, तो डेटा डिस्क्रिप्टर (लाइन 28-33) की __get__ विधि को कॉल करके विशेषता लुकअप को हल करें।


चूंकि टिप्पणियों में लोग और दो अन्य प्रश्नों में डुप्लिकेट के रूप में चिह्नित सभी इस तरह से उलझन में दिखाई देते हैं, मुझे लगता है कि एलेक्स कोवेन्ट्री के शीर्ष पर एक अतिरिक्त उत्तर जोड़ने के लायक है।

तथ्य यह है कि एलेक्स एक सूची की तरह एक परिवर्तनीय प्रकार का मूल्य निर्दिष्ट कर रहा है, इस बात से कोई लेना-देना नहीं है कि चीजें साझा की गई हैं या नहीं। हम इसे id फ़ंक्शन या ऑपरेटर के साथ देख सकते हैं:

>>> class A: foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
True
>>> class A:
...     def __init__(self): self.foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
False

(यदि आप सोच रहे हैं कि मैंने object() उपयोग क्यों किया, 5 कहें, तो यह दो अन्य सभी मुद्दों में भागने से बचने के लिए है, जिन्हें मैं यहां नहीं लेना चाहता हूं; दो अलग-अलग कारणों से, पूरी तरह से अलग-अलग 5 एस संख्या 5 का एक ही उदाहरण होने का अंत हो सकता है। लेकिन पूरी तरह से अलग-निर्मित object() एस नहीं कर सकते हैं।)

तो, यह क्यों है कि एलेक्स के उदाहरण में a.foo.append(5) b.foo प्रभावित करता है, लेकिन मेरे उदाहरण में a.foo = 5 नहीं है? खैर, एलेक्स के उदाहरण में a.foo = 5 आज़माएं, और ध्यान दें कि यह वहां b.foo को प्रभावित नहीं करता है।

a.foo = 5 सिर्फ 5 नाम पर a.foo बना रहा है। इससे b.foo या पुराने मान के लिए कोई अन्य नाम प्रभावित नहीं होता है जो a.foo को संदर्भित करता है। * यह थोड़ा मुश्किल है कि हम एक उदाहरण विशेषता बना रहे हैं जो क्लास विशेषता को छुपाता है, ** लेकिन एक बार जब आप इसे प्राप्त करें, यहां कुछ भी जटिल नहीं हो रहा है।

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

* सी ++ जैसी भाषा से आने वाले लोगों के लिए भ्रम यह है कि पायथन में, मान चर में संग्रहीत नहीं होते हैं। मूल्य मूल्य-भूमि में रहते हैं, स्वयं पर, चर केवल मूल्यों के लिए नाम होते हैं, और असाइनमेंट केवल मूल्य के लिए एक नया नाम बनाता है। यदि यह मदद करता है, तो प्रत्येक पायथन चर के बारे में एक shared_ptr<T> बजाय एक shared_ptr<T> रूप में सोचें।

** कुछ लोग एक क्लास एट्रिब्यूट का उपयोग करके एक उदाहरण विशेषता के लिए "डिफ़ॉल्ट मान" के रूप में इसका लाभ उठाते हैं जो उदाहरण सेट हो सकते हैं या नहीं भी हो सकते हैं। यह कुछ मामलों में उपयोगी हो सकता है, लेकिन यह भ्रमित भी हो सकता है, इसलिए इसके साथ सावधान रहें।


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

>>> class A: foo = []
>>> a, b = A(), A()
>>> a.foo.append(5)
>>> b.foo
[5]
>>> class A:
...  def __init__(self): self.foo = []
>>> a, b = A(), A()
>>> a.foo.append(5)
>>> b.foo    
[]






attributes