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




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

यहां एक बहुत अच्छी post , और इसे नीचे सारांशित करें।

class Bar(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
Bar.class_var
## 1
foo = MyClass(2)

## Finds i_var in foo's instance namespace
foo.i_var
## 2

## Doesn't find class_var in instance namespace…
## So look's in class namespace (Bar.__dict__)
foo.class_var
## 1

और दृश्य रूप में

कक्षा विशेषता असाइनमेंट

  • यदि कक्षा तक पहुंचने के द्वारा एक वर्ग विशेषता सेट की जाती है, तो यह सभी मामलों के मान को ओवरराइड कर देगी

    foo = Bar(2)
    foo.class_var
    ## 1
    Bar.class_var = 2
    foo.class_var
    ## 2
    
  • यदि किसी क्लास वेरिएबल को इंस्टेंस एक्सेस करके सेट किया गया है, तो यह केवल उस उदाहरण के लिए मान को ओवरराइड करेगा। यह अनिवार्य रूप से कक्षा चर को ओवरराइड करता है और इसे केवल उस उदाहरण के लिए उपलब्ध, एक आवृत्ति चर में उपलब्ध कराता है।

    foo = Bar(2)
    foo.class_var
    ## 1
    foo.class_var = 2
    foo.class_var
    ## 2
    Bar.class_var
    ## 1
    

आप वर्ग विशेषता का उपयोग कब करेंगे?

  • भंडारण स्थिरांक । चूंकि वर्ग विशेषताओं को कक्षा के गुणों के रूप में उपयोग किया जा सकता है, कक्षा-व्यापी, कक्षा-विशिष्ट स्थिरांक को संग्रहीत करने के लिए उनका उपयोग करना अक्सर अच्छा होता है

    class Circle(object):
         pi = 3.14159
    
         def __init__(self, radius):
              self.radius = radius   
        def area(self):
             return Circle.pi * self.radius * self.radius
    
    Circle.pi
    ## 3.14159
    c = Circle(10)
    c.pi
    ## 3.14159
    c.area()
    ## 314.159
    
  • डिफ़ॉल्ट मान परिभाषित करना । एक मामूली उदाहरण के रूप में, हम एक बाध्य सूची बना सकते हैं (यानी, एक सूची जो केवल कुछ निश्चित तत्वों या कम हो सकती है) और 10 आइटमों की डिफ़ॉल्ट कैप चुनना चुन सकते हैं

    class MyClass(object):
        limit = 10
    
        def __init__(self):
            self.data = []
        def item(self, i):
            return self.data[i]
    
        def add(self, e):
            if len(self.data) >= self.limit:
                raise Exception("Too many elements")
            self.data.append(e)
    
     MyClass.limit
     ## 10
    

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

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__ विधि को कॉल करके विशेषता लुकअप को हल करें।


एलेक्स कोवेन्ट्री ने जो कहा, उस पर एक विस्तार, एक अन्य एलेक्स (मार्टेलि) ने comp.lang.python newsgroup साल पहले इसी तरह के एक प्रश्न को संबोधित किया। वह उस व्यक्ति के अर्थपूर्ण अंतर की जांच करता है जो व्यक्ति को बनाम बना देता है (उदाहरण चर का उपयोग करके)।

http://groups.google.com/group/comp.lang.python/msg/5914d297aff35fae?hl=en


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

>>> 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    
[]

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

तथ्य यह है कि एलेक्स एक सूची की तरह एक परिवर्तनीय प्रकार का मूल्य निर्दिष्ट कर रहा है, इस बात से कोई लेना-देना नहीं है कि चीजें साझा की गई हैं या नहीं। हम इसे 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> रूप में सोचें।

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





attributes