2012-11-15 4 views
31

में विरासत वर्ग परिवर्तनीय संशोधन मैं एक कक्षा वर्ग को कक्षा चर को संशोधित करना चाहता हूं जो इसे अपने माता-पिता से प्राप्त होता है।पायथन

मैं की तर्ज पर कुछ करने के लिए करना चाहते हैं:

class Parent(object): 
    foobar = ["hello"] 

class Child(Parent): 
    # This does not work 
    foobar = foobar.extend(["world"]) 

और आदर्श है:

Child.foobar = ["hello", "world"] 

मैं कर सकता:

class Child(Parent): 
    def __init__(self): 
     type(self).foobar.extend(["world"]) 

लेकिन फिर हर बार जब मैं का दृष्टांत चाइल्ड का एक उदाहरण, "दुनिया" सूची में शामिल हो जाता है, जो अवांछित है। मैं इसे आगे संशोधित कर सकता हूं:

class Child(Parent): 
    def __init__(self): 
     if type(self).foobar.count("world") < 1: 
      type(self).foobar.extend(["world"]) 

लेकिन यह अभी भी हैक है क्योंकि मुझे इसे काम करने से पहले बच्चे के उदाहरण को तुरंत चालू करना होगा।

क्या कोई बेहतर तरीका है?

उत्तर

35

मान लिया जाये कि आप उपवर्ग में एक अलग सूची करना चाहते हैं, (के साथ शुरू के बाद से आप सिर्फ जगह में इसे संशोधित कर सका, या अपेक्षित मानों डाल जो व्यर्थ लगता है) माता-पिता वर्ग के सूची में बदलाव नहीं:

class Child(Parent): 
    foobar = Parent.foobar + ['world'] 

ध्यान दें कि यह विरासत से स्वतंत्र रूप से काम करता है, जो शायद एक अच्छी बात है।

+1

यह शानदार रूप से शानदार और सरल है! इसके अलावा, अगर बच्चे की विशेषता का प्रारंभ मूल्य माता-पिता की विशेषता के समान होना चाहिए, तो प्रतिलिपि आयात गहरी प्रतिलिपि से उपयोग करना उपयोगी होगा; foobar = deepcopy (parent.foobar) ' – zen11625

16

आपको अपने वर्ग चर में म्यूटेबल मानों का उपयोग नहीं करना चाहिए। बजाय उदाहरण पर इस तरह के मूल्यों को निर्धारित, __init__() उदाहरण प्रारंभकर्ता का उपयोग कर:

class Parent(object): 
    def __init__(self): 
     self.foobar = ['Hello'] 

class Child(Parent): 
    def __init__(self): 
     super(Child, self).__init__() 
     self.foobar.append('world') 

अन्यथा क्या में होता है कि foobar सूची न केवल उदाहरणों के बीच साझा किया जाता है, लेकिन उपवर्गों के साथ भी।

किसी भी मामले में, आपको विवादास्पद कक्षा चर के माध्यम से उदाहरणों के बीच राज्य साझा करने की इच्छा रखने के बावजूद आपको मूल कक्षाओं के उत्परिवर्तनों को संशोधित करने से बचना होगा;

class Parent(object): 
    foobar = ['Hello'] 

class Child(Parent): 
    foobar = Parent.foobar + ['world'] 

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

ऐसे मामलों में नेस्टेड उत्परिवर्तनों का ख्याल रखना; यदि आवश्यक हो तो गहरी प्रतियां बनाने के लिए copy मॉड्यूल का उपयोग करें।