अजगर कारखाने सबसे अच्छा कार्य करते हैं


30

मान लीजिए कि मेरे पास foo.pyएक क्लास वाली फाइल है Foo:

class Foo(object):
   def __init__(self, data):
      ...

अब मैं एक फ़ंक्शन जोड़ना चाहता हूं Fooजो कच्चे स्रोत डेटा से एक निश्चित तरीके से ऑब्जेक्ट बनाता है । क्या मुझे इसे फू में एक स्थिर विधि के रूप में या किसी अन्य अलग फ़ंक्शन के रूप में रखना चाहिए?

class Foo(object):
   def __init__(self, data):
      ...
# option 1:
   @staticmethod
   def fromSourceData(sourceData):
      return Foo(processData(sourceData))

# option 2:
def makeFoo(sourceData):
   return Foo(processData(sourceData))

मुझे नहीं पता कि उपयोगकर्ताओं के लिए सुविधाजनक होना अधिक महत्वपूर्ण है:

foo1 = foo.makeFoo(sourceData)

या क्या विधि और वर्ग के बीच स्पष्ट युग्मन बनाए रखना अधिक महत्वपूर्ण है:

foo1 = foo.Foo.fromSourceData(sourceData)

जवाबों:


45

पसंद कारखाने के फ़ंक्शन और इसके बजाय तीसरे विकल्प के बीच होनी चाहिए ; वर्ग विधि:

class Foo(object):
   def __init__(self, data):
      ...

   @classmethod
   def fromSourceData(klass, sourceData):
      return klass(processData(sourceData))

क्लासमेथोड कारखानों का अतिरिक्त लाभ है कि वे अंतर्निहित हैं। अब आप एक उपवर्ग बना सकते हैं Foo, और विरासत में मिली कारखाना विधि फिर उस उपवर्ग के उदाहरणों का निर्माण करेगी।

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

निम्नलिखित दो विकल्पों की तुलना करें:

foo.Foo.fromFrobnar(...)
foo.Foo.fromSpamNEggs(...)
foo.Foo.someComputedVersion()
foo.Bar.fromFrobnar(...)
foo.Bar.someComputedVersion()

बनाम

foo.createFooFromFrobnar()
foo.createFooFromSpamNEggs()
foo.createSomeComputedVersionFoo()
foo.createBarFromFrobnar()
foo.createSomeComputedVersionBar()

इससे भी बेहतर, आपका अंतिम-उपयोगकर्ता केवल Fooकक्षा का आयात कर सकता है और इसे विभिन्न तरीकों के लिए उपयोग कर सकता है जो आप इसे बना सकते हैं, क्योंकि आपके पास सभी कारखाने विधियाँ एक ही स्थान पर हैं:

from foo import Foo
Foo()
Foo.fromFrobnar(...)
Foo.fromSpamNEggs(...)
Foo.someComputedVersion()

Stdlib datetimeमॉड्यूल क्लास विधि कारखानों का बड़े पैमाने पर उपयोग करता है, और यह एपीआई इसके लिए बहुत स्पष्ट है।


बहुत बढ़िया जवाब। अधिक जानकारी के लिए @classmethod, शुरुआती के लिए @classmethod और @staticmethod का अर्थ
nealmcb

एंड-यूज़र
फ़ंक्शनलिटी

1

पायथन में, मैं आमतौर पर कारखाने के तरीकों पर एक वर्ग पदानुक्रम पसंद करता हूं। कुछ इस तरह:

class Foo(object):
    def __init__(self, data):
        pass

    def method(self, param):
        pass

class SpecialFoo(Foo):
    def __init__(self, param1, param2):
        # Some processing.
        super().__init__(data)

class FromFile(Foo):
    def __init__(self, path):
        # Some processing.
        super().__init__(data)

मैं पूरी पदानुक्रम (और केवल यह एक) एक मॉड्यूल में डालूँगा, कहते हैं foos.py। बेस क्लास Fooआमतौर पर सभी तरीकों (और जैसे कि, इंटरफ़ेस) को लागू करता है, और आमतौर पर उपयोगकर्ताओं द्वारा सीधे निर्माण नहीं किया जाता है। उपवर्ग बेस कंस्ट्रक्टर को अधिलेखित करने का एक माध्यम है, और निर्दिष्ट करना है कि Fooनिर्माण कैसे किया जाना है। तब मैं Fooउपयुक्त कंस्ट्रक्टर को कॉल करके बनाऊंगा, जैसे:

foo1 = mypackage.foos.SpecialFoo(param1, param2)
foo2 = mypackage.foos.FromFile('/path/to/foo')

मैं इसे स्टैटिक मेथड्स, क्लास मेथड्स या मॉड्यूल-लेवल फंक्शन्स से बनी फैक्ट्रियों से ज्यादा एलिगेंट और फ्लेक्सिबल पाता हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.