2012-02-03 6 views
5

मैं इस तरह एक डेकोरेटर के माध्यम से एक वर्ग के लिए कई डमी-गुण जोड़ने के लिए, चाहते हैं:मैं एक सजावट का उपयोग कर कक्षा में गुण कैसे जोड़ सकता हूं जो नामों की सूची तर्क के रूप में लेता है?

def addAttrs(attr_names): 
    def deco(cls): 
    for attr_name in attr_names: 
     def getAttr(self): 
     return getattr(self, "_" + attr_name) 
     def setAttr(self, value): 
     setattr(self, "_" + attr_name, value) 
     prop = property(getAttr, setAttr) 
     setattr(cls, attr_name, prop) 
     setattr(cls, "_" + attr_name, None) # Default value for that attribute 
    return cls 
    return deco 

@addAttrs(['x', 'y']) 
class MyClass(object): 
    pass 

दुर्भाग्य से, decoarator अपनी सामग्री के बजाय attr_name के संदर्भ रखने के लिए लगता है। इसलिए, MyClass.x और MyClass.y पहुंच दोनों MyClass._y:

a = MyClass() 
a.x = 5 
print a._x, a._y 
>>> None, 5 
a.y = 8 
print a._x, a._y 
>>> None, 8 

क्या मैं अपेक्षित व्यवहार प्राप्त करने के लिए बदलने के लिए है?

उत्तर

7

आप लगभग यह काम कर रहे थे। सिर्फ एक नाइट है। जब आंतरिक कार्यों बनाने, गेटर और सेटर कार्यों में attr_name के वर्तमान मूल्य के लिए बाध्य:

def addAttrs(attr_names): 
    def deco(cls): 
    for attr_name in attr_names: 
     def getAttr(self, attr_name=attr_name): 
     return getattr(self, "_" + attr_name) 
     def setAttr(self, value, attr_name=attr_name): 
     setattr(self, "_" + attr_name, value) 
     prop = property(getAttr, setAttr) 
     setattr(cls, attr_name, prop) 
     setattr(cls, "_" + attr_name, None) # Default value for that attribute 
    return cls 
    return deco 

@addAttrs(['x', 'y']) 
class MyClass(object): 
    pass 

यह उम्मीद परिणाम पैदा करता है:

>>> a = MyClass() 
>>> a.x = 5 
>>> print a._x, a._y 
5 None 
>>> a.y = 8 
>>> print a._x, a._y 
5 8 

आशा इस मदद करता है। हैप्पी सजाने :-)

2

पायथन ब्लॉक-स्तरीय स्कोपिंग का समर्थन नहीं करता है, केवल फ़ंक्शन-स्तर। इसलिए, लूप के भीतर आवंटित कोई भी चर लूप के बाहर उपलब्ध अंतिम मूल्य के रूप में उपलब्ध होगा। परिणाम आप देख रहे हैं पाने के लिए आपको पाश के भीतर एक बंद का उपयोग करने की आवश्यकता होगी:

def addAttrs(attr_names): 
    def deco(cls): 
    for attr_name in attr_names: 
     def closure(attr): 
     def getAttr(self): 
      return getattr(self, "_" + attr) 
     def setAttr(self, value): 
      setattr(self, "_" + attr, value) 
     prop = property(getAttr, setAttr) 
     setattr(cls, attr, prop) 
     setattr(cls, "_" + attr, None) 
     closure(attr_name) 
    return cls 
    return deco 

बंद closure, विशेषताओं के भीतर getAttr और setAttr सही ढंग से scoped किया जाएगा सौंपा का उपयोग करना।

संपादित करें: सही इंडेंटेशन

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