एक पायथन "संपत्ति" और "विशेषता" के बीच क्या अंतर है?


146

मैं आम तौर पर एक "संपत्ति" और एक "विशेषता" के बीच के अंतर के बारे में उलझन में हूं, और अंतरों को छिपाने के लिए एक महान संसाधन नहीं पा सकता हूं।

जवाबों:


184

गुण एक विशेष प्रकार की विशेषता है। मूल रूप से, जब पायथन का सामना निम्नलिखित कोड से होता है:

spam = SomeObject()
print(spam.eggs)

यह लग रहा है eggsमें spam, और उसके बाद की जांच करता है eggsअगर यह एक को देखने के लिए __get__, __set__या __delete__विधि - अगर यह होता है, यह एक संपत्ति है। यदि यह है एक संपत्ति के बजाय सिर्फ लौटने की eggsवस्तु (के रूप में यह किसी भी अन्य विशेषता के लिए) यह फोन करेगा __get__विधि और बदले जो कुछ भी विधि रिटर्न (क्योंकि हम देखने कर रहे थे)।

पायथन के डेटा मॉडल और विवरणकर्ताओं के बारे में अधिक जानकारी ।


ऐसा लगता है कि लक्ष्य मान तक पहुंचने के लिए संपत्तियों में अतिरिक्त प्रसंस्करण शामिल है ... क्या आप जानते हैं कि यह कितना महत्वपूर्ण / धीमा है?
मार्टीन्यू

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

56

एक संपत्ति के साथ आपके पास इसके गेटटर, सेटर और डेलेटर विधियों पर पूरा नियंत्रण होता है, जो आपके पास एक विशेषता के साथ (यदि कैविट्स का उपयोग नहीं कर रहा है) नहीं है।

class A(object):
    _x = 0
    '''A._x is an attribute'''

    @property
    def x(self):
        '''
        A.x is a property
        This is the getter method
        '''
        return self._x

    @x.setter
    def x(self, value):
        """
        This is the setter method
        where I can check it's not assigned a value < 0
        """
        if value < 0:
            raise ValueError("Must be >= 0")
        self._x = value

>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
  File "ex.py", line 15, in <module>
    a.x = -1
  File "ex.py", line 9, in x
    raise ValueError("Must be >= 0")
ValueError: Must be >= 0

यह ("पूर्ण नियंत्रण") "गैर-संपत्ति" विशेषताओं के साथ किया जा सकता है, हालांकि, ऐसे सरल सज्जाकार के बिना।

8
मुझे यह पसंद है कि यह उत्तर एक यथार्थवादी और उपयोगी उदाहरण प्रदान करता है। मुझे लगता है कि इस साइट पर बहुत सारे उत्तर अनावश्यक रूप से समझाते हैं कि उपयोगकर्ता बिना किसी को बताए कि कैसे उनके साथ बातचीत करनी चाहिए। यदि कोई यह नहीं समझता है कि कुछ कार्यक्षमता का उपयोग क्यों / कब करना है, तो यह जानने का कोई मतलब नहीं है कि यह पर्दे के पीछे कैसे संचालित होता है।
टॉम

यह जवाब "ज़ेन ऑफ पायथन - का उल्लंघन करता है - एक होना चाहिए - और अधिमानतः केवल एक - स्पष्ट तरीका यह करने के लिए"। X मान सेट करने के 2 तरीके हैं।
टीन

@TinLuu - x का मान सेट करने का केवल एक ही तरीका है। _X का मान सेट करने का केवल एक ही तरीका है। तथ्य यह है कि वे एक ही बात एक कार्यान्वयन विस्तार है। इस वर्ग के बुद्धिमान उपयोगकर्ता _x का उपयोग नहीं करते हैं।
प्रकाशित

1
@TinLuu - मुझे लगता है कि हम दोनों परिप्रेक्ष्य के विपरीत छोर से एक ही बात कह रहे हैं। वर्ग के उपयोगकर्ता को केवल देखना चाहिए x। एक रास्ता। यदि कक्षा के उपयोगकर्ता को _x के बारे में पता चलता है, तो वे इसका उपयोग अपने जोखिम पर करते हैं।
जलाया

19

सामान्य शब्दों में एक संपत्ति और एक विशेषता एक ही बात है। हालांकि, पायथन में एक संपत्ति डेकोरेटर है जो एक विशेषता (या अन्य डेटा) को गेट्टर / सेटर एक्सेस प्रदान करता है।

class MyObject(object):
    # This is a normal attribute
    foo = 1

    @property
    def bar(self):
        return self.foo

    @bar.setter
    def bar(self, value):
        self.foo = value


obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo

1
क्या आप कृपया इस कोड के अपेक्षित परिणाम का उल्लेख कर सकते हैं?
हसन इकबाल

2
आपका क्या अर्थ है? कोड के निचले भाग में नहीं है?
238 पर छह

12

संपत्ति आपको सामान्य विशेषताओं की तरह मान प्राप्त करने और सेट करने की अनुमति देती है, लेकिन इसके नीचे एक विधि है जिसे आप के लिए एक गेट्टर और सेटर में अनुवाद करना कहा जा रहा है। यह वास्तव में सिर्फ कॉलिंग गेटर्स और बसने वालों के बॉयलरप्लेट पर कटौती करने की सुविधा है।

उदाहरण के लिए कहते हैं, आपके पास एक ऐसा वर्ग था जो आपकी आवश्यकता के लिए कुछ x और y निर्देशांक रखता था। उन्हें सेट करने के लिए आप कुछ ऐसा करना चाहते हैं:

myObj.x = 5
myObj.y = 10

यह देखने और लिखने की तुलना में सोचने में बहुत आसान है:

myObj.setX(5)
myObj.setY(10)

समस्या यह है कि क्या होगा अगर एक दिन आपकी कक्षा ऐसी बदल जाए कि आपको अपने x और y को किसी मूल्य से ऑफसेट करने की आवश्यकता हो? अब आपको अपनी कक्षा की परिभाषा को बदलने और इसे कॉल करने वाले सभी कोड को बदलने की आवश्यकता होगी, जो वास्तव में समय लेने वाली और त्रुटि प्रवण हो सकती है। संपत्ति आपको बाद के परिवर्तन के लचीलेपन को देते हुए पूर्व वाक्यविन्यास का उपयोग करने की अनुमति देती है।

पायथन में, आप संपत्ति फ़ंक्शन के साथ गेटर्स, सेटर्स और डिलीट तरीकों को परिभाषित कर सकते हैं। यदि आप सिर्फ पढ़ी गई संपत्ति चाहते हैं, तो एक @property डेकोरेटर भी है जिसे आप अपने तरीके से जोड़ सकते हैं।

http://docs.python.org/library/functions.html#property


केवल वही उत्तर दिया जिसने व्यावहारिक अर्थ बनाया!
Dude156

8

मैंने सारांश में बेरंड क्लेन की साइट से 2 अंतर सीखे :

1. संपत्ति डेटा एनकैप्सुलेशन करने का एक अधिक सुविधाजनक तरीका है।

पूर्व: यदि आपकी कोई सार्वजनिक विशेषता ऑब्जेक्ट के बाद में है, तो बाद में, आपकी परियोजना को आपको इसे एनकैप्सुलेट करना होगा, अर्थात: इसे निजी में बदलें और गेट्टर और सेटर प्रदान करें => आपको पहले लिखे गए कई कोड बदलने होंगे:

#Old codes
obj1.length=obj1.length+obj2.length
#New codes(Using private attibutes and getter and setter)
obj1.set_lenght(obj1.get_length()+obj2.get_length()) #=> this is ugly

यदि आप @property और @ lenght.setter => का उपयोग करते हैं, तो आपको उन पुराने कोड को बदलने की आवश्यकता नहीं है

2. एक संपत्ति कई विशेषताओं को अतिक्रमण कर सकती है

class Person:
  def __init__(self, name, physic_health, mental_health):
    self.name=name
    self.__physic_health=physic_health #physic_health is real value in range [0, 5.0]
    self.__mental_health=mental_health #mental_health is real value in range [0, 5.0]
  @property
  def condition(self):
    health=self.__physic_health+self.__mental_health
    if(health<5.0):
      return "I feel bad!"
    elif health<8.0:
      return "I am ok!"
    else:
      return "Great!"

इस उदाहरण में, __physic_healthऔर __mental_healthनिजी हैं और उन्हें सीधे बाहर से एक्सेस नहीं किया जा सकता है, उनके साथ कक्षा के बाहर बातचीत का एकमात्र तरीका संपत्ति हैcondition


8

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

class Misc():
        def __init__(self):
            self.test = self.test_func()

        def test_func(self):
            print 'func running'
            return 'func value'

cl = Misc()
print cl.test
print cl.test

आउटपुट:

func running
func value
func value

हमने विशेषता को दो बार एक्सेस किया लेकिन हमारा फ़ंक्शन केवल एक बार निकाल दिया गया था। संपत्ति का उपयोग करने के लिए उपरोक्त उदाहरण को बदलने से आपके द्वारा उपयोग किए जाने पर प्रत्येक बार विशेषता का मूल्य ताज़ा हो जाएगा:

class Misc():

    @property
    def test(self):
        print 'func running'
        return 'func value'

cl = Misc()
print cl.test
print cl.test

आउटपुट:

func running
func value
func running
func value
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.