पायथन में क्लास डेकोरेटर्स: व्यावहारिक उपयोग के मामले


9

मैं पायथन क्लास डेकोरेटर्स के व्यावहारिक और गैर-सिंथेटिक उपयोग के मामलों की तलाश कर रहा हूं। अब तक, केवल एक मामला जिसने मेरे लिए समझ में आता है, वह एक प्रकाशक-ग्राहक प्रणाली में एक वर्ग को पंजीकृत कर रहा है, जैसे प्लगइन्स या ईवेंट, कुछ:

@register
class MyPlugin(Plugin):
    pass

या

@recieves_notifications
class Console:
    def print(self, text):
        ...

मेरे द्वारा किए गए किसी भी अन्य समझदार मामलों को विरासत, मेटाक्लासेस या सजाने के तरीकों के शीर्ष पर बनाया जा सकता था। क्या आप क्लास डेकोरेटर्स का उपयोग करने के लिए कोई अच्छा (या बुरा!) उदाहरण साझा कर सकते हैं।

धन्यवाद!


शुरुआत के लिए, सज्जाकार मेटाक्लासेस की तुलना में वैचारिक रूप से बहुत सरल हैं। यह बहुत आसान है कि एक मेटाक्लर की तुलना में एक डेकोरेटर लिखना है, और संभवतः यह पता लगाने से बचता है कि बिना किसी ब्रेक के कई मेटाक्लासेस को कैसे संयोजित किया जाए।
आमोन

@amon जब एक मेटाक्लर का उपयोग अनुभवी डेवलपर द्वारा किया जाता है, तो इसका आमतौर पर मतलब होता है कि अन्य विकल्पों पर अच्छी तरह से विचार किया गया है और मेटाक्लास अब तक समस्या को हल करने का सबसे अच्छा तरीका है। इसके अलावा, स्पष्ट निहितार्थ से बेहतर है - यही कारण हो सकता है कि (उदाहरण के रूप में) हमारे पास वर्ग सज्जाकार ABCMetaनहीं है @abstractclass
ज़ौर नसीबोव

2
मैं एक पायथन प्रोग्रामर हूं, और मैं ईमानदारी से उनके लिए एक आवश्यकता नहीं देखता हूं। सिर्फ इसलिए कि एक भाषा सुविधा मौजूद है इसका मतलब यह नहीं है कि आपको इसका उपयोग करना चाहिए या यहां तक ​​कि इसका उपयोग भी करना चाहिए। डिजाइनर सभी प्रकार की पागल विशेषताओं के साथ आते हैं जो अनावश्यक रूप से या यहां तक ​​कि बाधा के साथ हानिकारक होते हैं। वास्तव में, आपने अपने प्रश्न में इस तरह की दो अन्य विशेषताओं का उल्लेख किया है :)
गार्डेनहेड

1
कुछ ऐसा नहीं है जिसके बिना मैं नहीं रह सकता था, लेकिन मुझे जो कुछ उपयोगी लगा है वह है क्लास के सभी तरीकों के सभी इनपुट और आउटपुट को लॉग करने के लिए क्लास डेकोरेटर का उपयोग करना।
bgusach

जवाबों:


8

जब इकाई परीक्षण लिखने @unittest.skipIfऔर @unittest.skipUnlessव्यक्तिगत तरीकों पर या एक पूरी unittest.TestCaseकक्षा परिभाषा पर इस्तेमाल किया जा सकता है । यह प्लेटफ़ॉर्म विशिष्ट समस्याओं के लिए परीक्षण लिखने को इतना आसान बनाता है।

उदाहरण से asyncio/test_selectors

# Some platforms don't define the select.kqueue object for these tests.
# On those platforms, this entire grouping of tests will be skipped.

@unittest.skipUnless(hasattr(selectors, 'KqueueSelector'),
                 "Test needs selectors.KqueueSelector)")
class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
...

2

कक्षा सज्जाकार स्पष्ट रूप से कुछ चीजें हैं जो पहले से ही अधिक सुखद metaclasses के माध्यम से व्यक्त कर रहे थे, बनाने के लिए बनाया गया था पीईपी से :

प्रेरक उपयोग-मामला कुछ निर्माणों को आसानी से व्यक्त करने और CPython दुभाषिया के कार्यान्वयन विवरणों पर कम निर्भर बनाने के लिए था। हालांकि मेटाक्लस का उपयोग करके क्लास डेकोरेटर जैसी कार्यक्षमता को व्यक्त करना संभव है, परिणाम आम तौर पर अप्रिय और कार्यान्वयन अत्यधिक नाजुक होते हैं। इसके अलावा, मेटाक्लेज़ को विरासत में मिला है, जबकि क्लास डेकोरेटर्स नहीं हैं, कुछ के लिए मेटासेक्लेस को अनुपयुक्त बना रहे हैं, क्लास डेकोरेटर्स के सिंगल-क्लास-विशिष्ट उपयोग हैं। तथ्य यह है कि ज़ोप जैसी बड़े पैमाने पर पायथन परियोजनाएं इन जंगली विरोधाभासों से गुजर रही थीं ताकि बीडीएफएल पर जीते गए वर्ग सज्जाकारों की तरह कुछ हासिल किया जा सके।


PEP-3129 का हवाला देते हुए धन्यवाद। हालाँकि यह सवाल नहीं है कि क्लास डेकोरेटर्स क्यों मौजूद हैं, गुइडो उनके बारे में क्या सोचते हैं, और ज़ोप या आयरनपिथॉन उनके उभरने से पहले उनका इस्तेमाल कैसे कर सकते थे। सवाल उनके व्यावहारिक उपयोग के बारे में है, आज वर्ष 2016 में।
झोर नसीबोव

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

आप अधिक प्रश्नों को छोड़ रहे हैं जो उत्तर देते हैं। "... सज्जाकार का पूरा मुद्दा यह है कि वे उपयोग करने में आसान हैं और मेटाक्लासेस की तुलना में अधिक स्पष्ट हैं" - किन मामलों में? फिर "... आपको डेकोरेटर का उपयोग करना चाहिए क्योंकि वे दूसरों के लिए समझने में आसान हैं" वास्तव में? पायथन की लत के एक लंबे समय के लिए मैंने कुछ अति सुंदर, कुछ बदसूरत, मेटाक्लास के टन देखे हैं। लेकिन किसी भी वर्ग सज्जाकार की खोज नहीं की है।
Zaur Nasibov

1

से इस ढेर अतिप्रवाह सवाल:

def singleton(class_):
  instances = {}
  def getinstance(*args, **kwargs):
    if class_ not in instances:
        instances[class_] = class_(*args, **kwargs)
    return instances[class_]
  return getinstance

@singleton
class MyClass(BaseClass):
  pass

हां, लेकिन उसी एसओ प्रश्न में गर्भनिरोधक दिया गया है: मेटाक्लास एक बेहतर तरीका है।
नसीबोव

1

कक्षाओं पर सज्जाकार के साथ किए जा सकने वाले उपयोग के मामलों की तलाश निरर्थक है - कुछ भी जो कक्षाओं पर सज्जाकारों के साथ किया जा सकता है, मेटाक्लासेस के साथ किया जा सकता है। यहां तक ​​कि आपके पंजीकरण का उदाहरण भी। यह साबित करने के लिए, यहां एक मेटाक्लर है जो एक डेकोरेटर लागू करता है:

अजगर 2:

def register(target):
    print 'Registring', target
    return target


class ApplyDecorator(type):
    def __new__(mcs, name, bases, attrs):
        decorator = attrs.pop('_decorator')
        cls = type(name, bases, attrs)
        return decorator(cls)

    def __init__(cls, name, bases, attrs, decorator=None):
        super().__init__(name, bases, attrs)


class Foo:
    __metaclass__ = ApplyDecorator
    _decorator = register

अजगर 3:

def register(target):
    print('Registring', target)
    return target


class ApplyDecorator(type):
    def __new__(mcs, name, bases, attrs, decorator):
        cls = type(name, bases, attrs)
        return decorator(cls)

    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)


class Foo(metaclass=ApplyDecorator, decorator=register):
    pass

1
जैसा कि आप कहते हैं - डेकोरेटर के साथ कुछ भी किया जा सकता है। सवाल यह है कि ऐसे कौन से मामले हैं जो मेटाक्लस के बजाय क्लास डेकोरेटर्स के माध्यम से होने चाहिए
ज़ौर नसीबोव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.