2010-10-05 21 views
7

के साथ कक्षा परिभाषा पर लागू होते हैं, एक समारोह में लागू सजावटी की तुलना में, कक्षा में लागू सजावटी को समझना आसान नहीं होता है।सजावटी पाइथन

@foo 
class Bar(object): 
    def __init__(self, x): 
     self.x = x 
    def spam(self): 
     statements 

सजावट करने वालों के वर्ग का उपयोग करने का क्या मामला है? इसका इस्तेमाल कैसे करें?

उत्तर

23

यह कस्टम मेटाक्लास के लिए क्लासिक अच्छे उपयोगों के विशाल बहुमत को एक बहुत ही सरल तरीके से बदल देता है।

इस बारे में सोचें: क्लास बॉडी में सीधे कुछ भी नहीं है, क्लास ऑब्जेक्ट को संदर्भित कर सकता है, क्योंकि वर्ग ऑब्जेक्ट शरीर के चलने के बाद तक अस्तित्व में नहीं है (यह क्लास ऑब्जेक्ट बनाने के लिए मेटाक्लास का काम है - - आमतौर पर type, कस्टम मेटाक्लास के बिना सभी कक्षाओं के लिए)।

लेकिन, वर्ग डेकोरेटर में कोड के बाद वर्ग वस्तु (एक तर्क! के रूप में वास्तव में, वर्ग वस्तु के साथ) बनाया जाता है और इसलिए पूरी तरह से अच्छी तरह से (उस वर्ग वस्तु का उल्लेख कर सकते चलाता है और आम तौर पर ऐसा करने की जरूरत है)।

उदाहरण के लिए, पर विचार करें:

def enum(cls): 
    names = getattr(cls, 'names', None) 
    if names is None: 
    raise TypeError('%r must have a class field `names` to be an `enum`!', 
        cls.__name__) 
    for i, n in enumerate(names): 
    setattr(cls, n, i) 
    return cls 

@enum 
class Color(object): 
    names = 'red green blue'.split() 

और अब आप Color.red का उल्लेख कर सकते, Color.green, & ग, बल्कि 0 की तुलना में, 1, आदि (बेशक आप सामान्य रूप से बनाने के लिए और भी अधिक कार्यक्षमता जोड़ना होगा "एक enum", लेकिन यहां मैं कस्टम मेटाक्लास की आवश्यकता के बजाय कक्षा सजावट में ऐसी कार्यक्षमता को जोड़ने का सरल तरीका दिखा रहा हूं! -

+0

@Manoj, खुशी है कि आपको यह पसंद आया, मुझे बताए जाने के लिए टीएक्स! –

6

एक उपयोग केस जो मैं सोच सकता हूं वह है यदि आप चाहते हैं एक वर्ग के सभी तरीकों को लपेटो एक समारोह सजावट के साथ।

def logit(f): 
    def res(*args, **kwargs): 
     print "Calling %s" % f.__name__ 
     return f(*args, **kwargs) 
    return res 

और निम्न वर्ग:

>>> class Pointless: 
    def foo(self): print 'foo' 
    def bar(self): print 'bar' 
    def baz(self): print 'baz' 

>>> p = Pointless() 
>>> p.foo(); p.bar(); p.baz() 
foo 
bar 
baz 

आप सभी तरीकों को सजाने कर सकते हैं:

>>> class Pointless: 
    @logit 
    def foo(self): print 'foo' 
    @logit 
    def bar(self): print 'bar' 
    @logit 
    def baz(self): print 'baz' 

>>> p = Pointless() 
>>> p.foo(); p.bar(); p.baz() 
Calling foo 
foo 
Calling bar 
bar 
Calling baz 
baz 

लेकिन वह लंगड़ा है आप निम्नलिखित डेकोरेटर है की शुभकामनाएं दें! इसके बजाय आप यह कर सकते हैं:

>>> def logall(cls): 
for a in dir(cls): 
    if callable(getattr(cls, a)): 
     setattr(cls, a, logit(getattr(cls, a))) 
return cls 

>>> @logall 
class Pointless: 
    def foo(self): print 'foo' 
    def bar(self): print 'bar' 
    def baz(self): print 'baz' 

>>> p = Pointless() 
>>> p.foo(); p.bar(); p.baz() 
Calling foo 
foo 
Calling bar 
bar 
Calling baz 
baz 

अद्यतन: logall का एक और अधिक जेनेरिक वर्जन:

>>> def wrapall(method): 
    def dec(cls): 
     for a in dir(cls): 
      if callable(getattr(cls, a)): 
       setattr(cls, a, method(getattr(cls, a))) 
     return cls 
    return dec 

>>> @wrapall(logit) 
class Pointless: 
     def foo(self): print 'foo' 
     def bar(self): print 'bar' 
     def baz(self): print 'baz' 

>>> p = Pointless() 
>>> p.foo(); p.bar(); p.baz() 
Calling foo 
foo 
Calling bar 
bar 
Calling baz 
baz 
>>> 

पूर्ण प्रकटीकरण: मैं यह करने के लिए किया था कभी नहीं किया है और मैं सिर्फ इस उदाहरण बना हुआ है।

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