2009-06-29 4 views
5

यह प्रश्न this other one के समान है, इस अंतर के साथ कि बेस क्लास में डेटा सदस्य वर्णनकर्ता प्रोटोकॉल द्वारा लिपटा हुआ है।बेस क्लास के डेटा सदस्य को कॉल कैसे करें यदि इसे व्युत्पन्न कक्षा में किसी संपत्ति के रूप में अधिलेखित किया जा रहा है?

दूसरे शब्दों में, यदि मैं व्युत्पन्न कक्षा में किसी संपत्ति के साथ अपना नाम ओवरराइड कर रहा हूं तो मैं बेस क्लास के सदस्य तक कैसे पहुंच सकता हूं?

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

class Derived(Base): 
    def __init__(self): 
     Base.__init__(self) 

    @property 
    def foo(self): 
     return 1 + self.foo # doesn't work of course! 

    @foo.setter 
    def foo(self, f): 
     self._foo = f 

bar = Base() 
print bar.foo 

foobar = Derived() 
print foobar.foo 

कृपया ध्यान दें कि मैं भी क्योंकि अन्यथा आधार वर्ग में self.foo का काम काम नहीं करता है एक सेटर को परिभाषित करने की जरूरत है।

सभी वर्णनकर्ता प्रोटोकॉल के सभी, उदाहरण के एक सदस्य (विशेषता) विरासत के साथ ठीक से प्रतीत होता है नहीं ...

उत्तर

4

Base में

def __init__(self): 
    self.foo = 5 

परिभाषित करता है foo नहीं कक्षा का वर्गBase को foo का कोई ज्ञान नहीं है, इसलिए super() कॉल जैसी किसी चीज़ से इसे एक्सेस करने का कोई तरीका नहीं है।

हालांकि यह आवश्यक नहीं है। जब आप instanciate

foobar = Derived() 

और आधार वर्ग के __init__() प्रणाली को बुलाती है

self.foo = 5 

इस विशेषता के निर्माण/ओवरराइटिंग का कारण नहीं बनेगा, लेकिन इसके बजाय Derived के सेटर में, जिसका अर्थ है बुलाया जा रहा है

self.foo.fset(5) 

और इस तरह self._foo = 5। इसलिए यदि आप

return 1 + self._foo 

आपके गेटटर में, आपको बहुत कुछ मिलता है जो आप चाहते हैं। यदि आपको self.fooBase के कन्स्ट्रक्टर में सेट करने की आवश्यकता है, तो बस _foo पर देखें, जो @foo.setter द्वारा सही ढंग से सेट किया गया था।

+0

सभी उत्तर बहुत ही दिलचस्प होते हैं और मैं उनमें से ज्यादातर upvoted लेकिन यह एक सीधे करने के लिए था बिंदु, यह वास्तव में मुझे हाथ में समस्या समझ में आया। – UncleZeiv

0

एक बार आप एक ही नाम 'foo' के साथ संपत्ति है यह नाम 'foo' की पहुँच के व्यवहार को ओवरराइड करता है एक ही तरीका है बाहर लगता है कि आप स्पष्ट रूप dict

btw में 'foo' सेट है कि: मैं अजगर का उपयोग 2.5 इसलिए कोड को थोड़ा

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

class Derived(Base): 
    def __init__(self): 
     Base.__init__(self) 

    def g_foo(self): 
     return 1 + self.__dict__['foo'] # works now! 

    def s_foo(self, f): 
     self.__dict__['foo'] = f 
     self._foo = f 

    foo = property(g_foo, s_foo) 

bar = Base() 
print bar.foo 

foobar = Derived() 
print foobar.foo 
9

जीवन आसान है यदि आप विरासत के बजाय प्रतिनिधिमंडल का उपयोग करते हैं। यह पायथन है। आप Base से उत्तराधिकारी के लिए बाध्य नहीं हैं।

class LooksLikeDerived(object): 
    def __init__(self): 
     self.base= Base() 

    @property 
    def foo(self): 
     return 1 + self.base.foo # always works 

    @foo.setter 
    def foo(self, f): 
     self.base.foo = f 

लेकिन बेस के अन्य तरीकों के बारे में क्या? आप नाम LooksLikeDerived और बस में डुप्लिकेट करते हैं।

def someMethodOfBase(self, *args, **kw): 
    return self.base.someMethodOfBase(*args **kw) 

हां, यह "DRY" महसूस नहीं करता है। हालांकि, यह नई कार्यक्षमता में कुछ वर्ग को "लपेटने" जैसी कई समस्याओं को रोकता है जैसे आप करने की कोशिश कर रहे हैं।

+0

हाँ, मैं वास्तव में अपने कोड को व्यवस्थित करने के लिए और अधिक "पायथन" तरीकों की तलाश में हूं, और मैं थोड़ी देर के लिए अपने विरासत-आधारित दृष्टिकोण पर सवाल उठा रहा हूं। आपका विकल्प, हालांकि, मेरे मामले में यह विश्वास नहीं है, क्योंकि मेरे पास कई स्तरों की गहरी विरासत श्रृंखला है, जहां प्रत्येक स्तर नई सुविधाओं को परिभाषित करता है। प्रत्येक स्तर पर सभी विधियों को फिर से परिभाषित करने के लिए निश्चित रूप से असुरक्षित होगा। लेकिन मैं आपकी बात देखता हूँ। – UncleZeiv

+0

@UncleZeiv: यह एक ईथर या स्थिति नहीं है। आपके पास रणनीति, संरचना, प्रतिनिधिमंडल और विरासत सहित कई, कई डिज़ाइन पैटर्न हैं। विरासत पर ध्यान केंद्रित एक बुरी बात है। –

1
class Foo(object): 
    def __new__(cls, *args, **kw): 
     return object.__new__(cls, *args, **kw) 

    def __init__(self): 
     self.foo = 5 

class Bar(Foo): 
    def __new__(cls, *args, **kw): 
     self = object.__new__(cls, *args, **kw) 
     self.__foo = Foo.__new__(Foo) 
     return self 

    def __init__(self): 
     Foo.__init__(self) 

    @property 
    def foo(self): 
     return 1 + self.__foo.foo 

    @foo.setter 
    def foo(self, foo): 
     self.__foo.foo = foo 

bar = Bar() 
bar.foo = 10 
print bar.foo 
0

सच में, पर यहाँ देखने के लिए बात यह है कि आप एक डिजाइन बस गरीब है कि चारों ओर अपने कोड मोड़ की कोशिश कर रहे है। संपत्ति वर्णनकर्ता 'foo' विशेषता के अनुरोध को संभालते हैं, और आप इन्हें पूरी तरह से बाईपास करना चाहते हैं, जो कि गलत है। आप पहले ही बेस बना रहे हैं। init foobar._foo = 5 असाइन करने के लिए, इसलिए वही है जहां गेटर को भी देखना चाहिए।

वर्ग बेस (वस्तु): डीईएफ़ init (स्वयं): self.foo = 5

class Derived(Base): 
    def __init__(self): 
    Base.__init__(self) 

    @property 
    def foo(self): 
    return 1 + self._foo # DOES work of course! 

    @foo.setter 
    def foo(self, f): 
    self._foo = f 

bar = Base() 
print bar.foo 

foobar = Derived() 
print foobar.foo 
संबंधित मुद्दे

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