पायथन में IoC / DI आम क्यों नहीं है?


312

जावा में आईओसी / डीआई एक बहुत ही आम प्रथा है जो बड़े पैमाने पर वेब अनुप्रयोगों, लगभग सभी उपलब्ध रूपरेखाओं और जावा ईई में उपयोग की जाती है। दूसरी ओर, बहुत सारे बड़े पायथन वेब एप्लिकेशन भी हैं, लेकिन ज़ोप के बगल में (जिसे मैंने सुना है कि वास्तव में कोड के लिए भयानक होना चाहिए) IoC पायथन दुनिया में बहुत आम नहीं लगता है। (कृपया कुछ उदाहरणों को नाम दें यदि आपको लगता है कि मैं गलत हूं)।

उदाहरण के लिए पाइथन, स्प्रिंगपीथॉन के लिए लोकप्रिय जावा आईओसी फ्रेमवर्क के कई क्लोन उपलब्ध हैं । लेकिन उनमें से कोई भी व्यावहारिक रूप से उपयोग करने के लिए नहीं लगता है। कम से कम, मैं एक Django पर कभी नहीं ठोकर खाई है या sqlalchemy + <insert your favorite wsgi toolkit here>आधारित वेब एप्लिकेशन जो ऐसा कुछ उपयोग करता है।

मेरी राय में IoC के उचित लाभ हैं और उदाहरण के लिए django-default-user-model को प्रतिस्थापित करना आसान होगा, लेकिन पायथन में इंटरफ़ेस क्लासेस और IoC का व्यापक उपयोग थोड़ा अजीब लगता है और न कि »pythonic«। लेकिन शायद किसी के पास एक बेहतर स्पष्टीकरण है, क्यों IoC का व्यापक रूप से पायथन में उपयोग नहीं किया जाता है।


2
मेरा अनुमान है, यही कारण है कि रूबी में यह कम लोकप्रिय है, बिल्ट-इन मिक्सिन्स और ओपन क्लासेस
सैम सैफ्रन

3
क्या आपने कभी स्प्रिंगपीथॉन की कोशिश की? यह विज्ञापित के रूप में भी काम नहीं करता है। कम से कम एनओपी हिस्से में। जब तक आप जावा से नहीं आ रहे हैं और संक्रमण के दौरान आराम के कुछ स्तर की आवश्यकता है, तब तक वहां सब कुछ बहुत उपयोगी नहीं है।
टॉम विलिस

6
कृपया ध्यान रखें कि DI के उपयोग, और IOC ढांचे के उपयोग के बीच अंतर करना। पूर्व एक डिजाइन पैटर्न है, बाद वाला पूर्व के स्वचालित उपयोग में सहायता करने के लिए एक रूपरेखा है।
डग

डौग, मेरा मानना ​​है कि आपका कहना है कि डीआई एक रचनात्मक विशेषता है जो डेकोरेटर पैटर्न का उपयोग करके प्राप्त की जाती है।
njappboy

4
मुझे एक उत्तर देखने में अच्छा लगेगा, जो वास्तविक दुनिया की समस्याओं को हल करता है जो DI हल करता है: लाइफटाइम प्रबंधन, टेस्ट स्टबिंग की आसानी, आदि। यदि इन से निपटने के लिए एक और अधिक पायथोनिक तरीका है, तो मैं सभी कान हूं।
जोश नोह

जवाबों:


197

मैं वास्तव में नहीं लगता है कि डि / आईओसी हैं करते हैं कि अजगर में असामान्य। हालांकि, असामान्य क्या है , DI / IoC चौखटे / कंटेनर हैं

इसके बारे में सोचें: DI कंटेनर क्या करता है? यह आपको अनुमति देता है

  1. एक स्वतंत्र अनुप्रयोग में एक साथ स्वतंत्र घटक तार ...
  2. ... चलने के समय पर।

हमारे पास "एक साथ वायरिंग" और "रनटाइम पर" के नाम हैं:

  1. पटकथा
  2. गतिशील

इसलिए, एक DI कंटेनर एक गतिशील स्क्रिप्टिंग भाषा के लिए एक दुभाषिया के अलावा कुछ भी नहीं है। वास्तव में, मुझे यह बताने की आवश्यकता है कि: एक सामान्य जावा / .NET DI कंटेनर कुछ भी नहीं है लेकिन वास्तव में खराब गतिशील स्क्रिप्टिंग भाषा के लिए बट-बदसूरत, कभी-कभी XML- आधारित, सिंटैक्स के साथ एक भद्दा दुभाषिया है।

जब आप पायथन में कार्यक्रम करते हैं, तो अपने निपटान में एक सुंदर, शानदार पटकथा भाषा होने पर आप एक बदसूरत, खराब स्क्रिप्टिंग भाषा का उपयोग क्यों करना चाहेंगे? वास्तव में, यह एक अधिक सामान्य प्रश्न है: जब आप किसी भी भाषा में बहुत अधिक प्रोग्राम करते हैं, तो आप अपने निपटान में जाइथन और आयरनपिथॉन होने पर एक बदसूरत, खराब स्क्रिप्टिंग भाषा का उपयोग क्यों करना चाहेंगे?

इसलिए, पुनरावृत्ति करने के लिए: DI / IoC का अभ्यास ठीक वैसा ही महत्वपूर्ण है जैसा कि जावा में है, ठीक उसी कारणों से। हालांकि DI / IoC का कार्यान्वयन भाषा में बनाया गया है और अक्सर इतना हल्का होता है कि यह पूरी तरह से गायब हो जाता है।

(यहाँ एक सादृश्य के लिए एक संक्षिप्त विवरण दिया गया है: असेंबली में, एक सबरूटीन कॉल एक बहुत बड़ी बात है - आपको अपने स्थानीय चरों और रजिस्टरों को मेमोरी में सहेजना होगा, अपना रिटर्न एड्रेस कहीं बचाना होगा, निर्देश सूचक को आपके द्वारा कॉल किए जाने वाले सबरूटीन में बदलना होगा, इसे समाप्त करने के लिए किसी तरह से वापस अपने सबरूटीन में कूदने की व्यवस्था करें, जहां कहीं भी कैली उन्हें मिल सकती है, वहां तर्क रखें और इसी तरह। IOW: असेंबली में, "सबरूटीन कॉल" एक डिज़ाइन पैटर्न है, और इससे पहले जैसी भाषाएं हैं। फोरट्रान जिसकी उप-निर्मित कॉल थी, लोग अपने "सबरूटीन फ्रेमवर्क" का निर्माण कर रहे थे। क्या आप कहेंगे कि सबरूटीन कॉल पायथन में "असामान्य" हैं, सिर्फ इसलिए कि आप सबरूटीन फ्रेमवर्क का उपयोग नहीं करते हैं?)

BTW: DI को अपने तार्किक निष्कर्ष पर ले जाने के लिए कैसा दिखता है, इसके एक उदाहरण के लिए, गिल्ड ब्राचा के समाचारपत्र प्रोग्रामिंग भाषा और इस विषय पर उनके लेखन पर एक नज़र डालें :


58
जबकि मैं सहमत हूं। एक्सएमएल टिप्पणी गलत है। कई (कम से कम आधुनिक) IOC कंटेनर कॉन्फ़िगरेशन (XML) पर कन्वेंशन (कोड) का उपयोग करते हैं।
फिंगलस

20
आपको जावा में वायरिंग को स्पष्ट रूप से लिखने से रोकने के लिए कुछ भी नहीं है, लेकिन जैसा कि आपके पास अधिक से अधिक सेवाएं हैं, निर्भरताएं अधिक जटिल हैं। DI कंटेनर मेक की तरह है: आप निर्भरता की घोषणा करते हैं और कंटेनर उन्हें सही क्रम में आरंभ करता है। Guice एक Java DI फ्रेमवर्क है जहाँ सब कुछ Java कोड में लिखा जाता है। डिक्लेयरली लिखने से डीआई कंटेनर इनिशियलाइज़ेशन से पहले डिक्लेरेशन प्रोसेस करने के लिए सपोर्ट भी जोड़ता है (उदाहरण के लिए, प्रॉपर्टी प्लेसहोल्डर्स को वास्तविक मानों से बदलें)
इट्टीडीडी

133
"हालांकि, DI / IoC का कार्यान्वयन भाषा में बनाया गया है और अक्सर इतना हल्का होता है कि यह पूरी तरह से गायब हो जाता है।" वोट डाउन करें क्योंकि यह स्पष्ट रूप से असत्य है। DI एक पैटर्न है जहां एक इंटरफ़ेस को कंस्ट्रक्टर में पास किया जाता है। यह अजगर में बिल्ट-इन नहीं है।
डग

146
डाउनवोट, वायरिंग का स्क्रिप्टिंग से कोई लेना-देना नहीं है, DI एक पैटर्न है, और यह स्क्रिप्टिंग के बराबर नहीं है
Luxspes

38
मैं इससे असहमत हूं। DI स्थिर भाषाओं में गतिशील स्क्रिप्टिंग की कमी को हल नहीं करता है। यह आपके एप्लिकेशन के हिस्सों को कॉन्फ़िगर और कंपोज़ करने के लिए एक फ्रेमवर्क प्रदान करता है। मैंने एक बार एक रूबी देव को यह कहते सुना था कि गतिशील भाषाओं में DI अनावश्यक है। लेकिन उन्होंने रेल का उपयोग किया ... रेल केवल एक बड़ा डीआई कंटेनर है, जो कन्वेंशन का उपयोग यह पता लगाने के लिए करता है कि कौन से भागों को कब कॉन्फ़िगर करना है। उन्हें DI की आवश्यकता नहीं थी क्योंकि रेल ने उनके लिए पुर्जे खोजने की समस्या को हल कर दिया था।
ब्रायन जेनिसियो

51

इसका एक तरीका यह है कि पाइथन में मॉड्यूल सिस्टम काम करता है। आप केवल एक मॉड्यूल से आयात करके, मुफ्त में "सिंगलटन" प्राप्त कर सकते हैं। किसी मॉड्यूल में किसी ऑब्जेक्ट के वास्तविक उदाहरण को परिभाषित करें, और फिर कोई भी क्लाइंट कोड इसे आयात कर सकता है और वास्तव में एक काम कर सकता है, पूरी तरह से निर्मित / आबादी वाली वस्तु।

यह जावा के विपरीत है, जहाँ आप वस्तुओं के वास्तविक उदाहरणों का आयात नहीं करते हैं। इसका मतलब है कि आप हमेशा उन्हें खुद को त्वरित करने के लिए कर रहे हैं, (या कुछ प्रकार के IoC / DI शैली दृष्टिकोण का उपयोग करें)। आप स्थैतिक फ़ैक्टरी विधियों (या वास्तविक फैक्ट्री क्लासेस) के द्वारा सब कुछ तुरंत करने के झंझट को कम कर सकते हैं, लेकिन फिर भी आप वास्तव में हर बार नए निर्माण करने वाले संसाधन उपरि का उपयोग करते हैं।


2
यह समझ आता है। यदि मैं पायथन में एक कार्यान्वयन को बदलना चाहता हूं, तो मैं एक ही नाम का उपयोग करके एक अलग स्थान से आयात करता हूं। लेकिन अब मैं सोच रहा हूं कि क्या जावा में MyClassInstancesप्रत्येक को एक कक्षा को परिभाषित करके दूसरा रास्ता भी संभव है MyClass, जिसमें केवल स्थिर, पूरी तरह से प्रारंभिक उदाहरण हैं। यह वायर्ड किया जाएगा: D
tux21b

2
और एक अन्य विचार: अजगर में इस तरह के आयात को बदलने का एक तरीका प्रदान करने से यह संभव होगा कि सभी अजगर फ़ाइलों को छूने के बिना कार्यान्वयन को आसानी से प्रतिस्थापित किया जा सके। इसके बजाय फ्रेमवर्क के अंदर (दूसरा पैरामीटर डिफ़ॉल्ट मान हो सकता है) from framework.auth.user import User लिखना बेहतर User = lookup('UserImplentation', 'framework.auth.user.User')होगा। तब फ्रेमवर्क के उपयोगकर्ता फ्रेमवर्क को Userछूने के बिना कार्यान्वयन को बदलने / विशेषज्ञ करने में सक्षम होंगे ।
tux21b

14
वास्तविक जीवन में, आपको जवाब देना, आपको शायद ही कभी "एक सिंगलटन" की आवश्यकता है, आपको गुंजाइश को नियंत्रित करने की आवश्यकता है (आपको थ्रेड स्थानीय सिंगलटन, या एक सत्र सिंगलटन, और इसी तरह की आवश्यकता हो सकती है), यह मुझे लगता है कि समस्याओं की तरह पायथन में हल वास्तविक दुनिया की समस्याओं की तरह एक उद्यम सेटिंग में हल नहीं कर रहे हैं
Luxspes

3
वास्तव में DI कोड की निर्भरता का परीक्षण करने और उसे समझने में सक्षम है। इसके अलावा आयात की सुविधा जावा में स्थैतिक आयात के समान है, जो मुझे किसी वस्तु का एकल उदाहरण आयात करने देता है।
रिचर्ड वॉर्बटन ने

1
"आप एक मॉड्यूल से आयात करके, केवल एक प्रकार का" सिंगलटन "मुफ्त में प्राप्त कर सकते हैं।" जावा में एक स्थैतिक उदाहरण क्षेत्र की घोषणा करके और इसे एक मूल्य पर सेट करके आसानी से किया जा सकता है। यह एक
सॉलिड

45

Io और DI परिपक्व पायथन कोड में सुपर कॉमन हैं। बतख टाइपिंग के लिए DI धन्यवाद लागू करने के लिए आपको बस एक रूपरेखा की आवश्यकता नहीं है।

सबसे अच्छा उदाहरण है कि आप कैसे प्रयोग करके Django एप्लिकेशन सेट करते हैं settings.py:

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': REDIS_URL + '/1',
    },
    'local': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'snowflake',
    }
}

Django रेस्ट फ्रेमवर्क DI का भारी उपयोग करता है:

class FooView(APIView):
    # The "injected" dependencies:
    permission_classes = (IsAuthenticated, )
    throttle_classes = (ScopedRateThrottle, )
    parser_classes = (parsers.FormParser, parsers.JSONParser, parsers.MultiPartParser)
    renderer_classes = (renderers.JSONRenderer,)

    def get(self, request, *args, **kwargs):
        pass

    def post(self, request, *args, **kwargs):
        pass

मुझे याद दिलाने ( स्रोत ):

"निर्भरता इंजेक्शन" 5-प्रतिशत अवधारणा के लिए 25-डॉलर का शब्द है। [...] निर्भरता इंजेक्शन का अर्थ है किसी वस्तु को उसके उदाहरण चर देना। [...]।


8
+1। अच्छे से कहा। पायथन प्रोग्रामर होने के नाते मैं पूरी तरह से सी # में डीआई फ्रेमवर्क पर एक पूरी साक्षात्कार प्रस्तुति से चकित था। मुझे यह महसूस करने में थोड़ा समय लगा कि मैंने पहले से ही फ्लास्क ऐप्स में हर समय यह किया है कि इसके बारे में सोचे बिना भी आपको फ्रेमवर्क की आवश्यकता नहीं है। किसी ऐसे व्यक्ति के लिए जो C # / Java से परे कुछ भी नहीं जानता है, यह प्रश्न समझ में आता है। बतख-टाइप किए गए भाषा प्रोग्रामर के लिए यह स्वाभाविक है और जैसा कि आप कहते हैं, "5-प्रतिशत अवधारणा के लिए 25-डॉलर का शब्द"।
सैमुअल हैमर

5
गलत ... यह निर्भरता इंजेक्शन नहीं है क्योंकि इंस्टेंसेस ( IsAuthenticated, ScopedRateThrottle) वर्ग द्वारा त्वरित हैं। उन्हें कंस्ट्रक्टर में पारित नहीं किया गया है।
डोपाट्रमण '

5
IsAuthenticatedऔर ScopedRateThrottleउदाहरण नहीं हैं, ये कक्षाएं हैं। जब एक FooView का निर्माण किया जाता है, तो वे तुरंत हो जाते हैं (वास्तव में, जब FooView एक अनुरोध संसाधित करता है)। वैसे भी, यह केवल एक कार्यान्वयन विवरण है। IsAuthenticatedऔर ScopedRateThrottleनिर्भरताएं हैं; वे में इंजेक्ट कर रहे हैं FooView। यह कब या कैसे किया जाता है, इससे कोई फर्क नहीं पड़ता । अजगर जावा नहीं है, इसलिए इसे लागू करने के विभिन्न तरीके हैं।
मैक्स मालेश

3
@MaxMalysh मैं इस पर dopatraman से सहमत हूँ। यह भी IoC नहीं है क्योंकि वर्ग में ही विशिष्ट वर्ग के लिए "हार्डकोड" निर्भरताएं हैं। IoC में, हार्डकॉस्ट के बजाय निर्भरता शॉल्ड प्रदान की जाती है। उस के शीर्ष पर, निर्भरता इंजेक्शन में, आपके पास प्रत्येक सेवा के जीवन चक्रों के प्रबंधन के लिए एक इकाई होगी और जब ऐसा हो तो उन्हें इंजेक्ट करें। समाधान उनमें से किसी में नहीं दिया गया है।
रिकार्डो ने

3
@alex नहीं, आपको किसी अन्य रेंडरर का उपयोग करने के लिए अपना कोड बदलने की आवश्यकता नहीं है। तुम भी एक साथ कई रेंडरर्स का उपयोग कर सकते हैं renderer_classes = (JSONRenderer, BrowsableAPIRenderer, XMLRenderer):। मॉकिंग करना उतना ही सरल है @unittest.patch('myapp.views.FooView.permission_classes')। जावा को संकलित और वैधानिक रूप से टाइप की गई भाषा में मजबूत मेटाप्रोग्रामिंग क्षमताओं की कमी के कारण "कुछ करने के लिए" जावा चीजों को करने के लिए एक हताश "परिणाम" की आवश्यकता है।
मैक्स मलिश

35

Django नियंत्रण के व्युत्क्रम का बहुत उपयोग करता है। उदाहरण के लिए, डेटाबेस सर्वर को कॉन्फ़िगरेशन फ़ाइल द्वारा चुना जाता है, फिर फ्रेमवर्क डेटाबेस क्लाइंट को उपयुक्त डेटाबेस आवरण उदाहरण प्रदान करता है।

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

if config_dbms_name == 'postgresql':
    import psycopg
    self.database_interface = psycopg
elif config_dbms_name == 'mysql':
    ...

बाद में कोड लिखकर एक डेटाबेस इंटरफ़ेस बना सकते हैं:

my_db_connection = self.database_interface()
# Do stuff with database.

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


4
जिसे आप कोड कहते हैं, वह वास्तव में वायरिंग हिस्सा है। यह आपके ioc फ्रेमवर्क का XML होगा। यह वास्तव में बस के रूप में लिखा जा सकता है import psycopg2 as database_interface। उस लाइन को injections.pyएट वॉयला में रखो ।
स्पेक्ट्रा

29
ईआरएम। आपका क्या कर रहा है वहाँ बहुत पाठ्यपुस्तक अनिवार्य डैनियल है।
Shayne

यह निश्चित रूप से अनिवार्य कोड है, लेकिन यह एक प्रकार का कार्यात्मक है क्योंकि यह मूल्य के रूप में एक कॉल करने योग्य का उपयोग करता है।
जेरेमी

5
हालांकि यह सिर्फ प्रथम श्रेणी के कार्य नहीं है? en.wikipedia.org/wiki/First-class_function सिर्फ इसलिए कि आपके पास है और उनका उपयोग आपके कोड को कार्यात्मक नहीं बनाता है। यहां काफी कुछ साइड इफेक्ट्स हो रहे हैं (जैसे बदलना self.database_interface), जो जरूरी है।
hjc1710

15

इससे पता चलता है कि लोगों को न तो वह मिलता है जो डिपेंडेंसी इंजेक्शन और नियंत्रण का उलटा मतलब है।

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

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

यदि आप किसी वस्तु को पैकेज के अंदर रख सकते हैं और उसे स्वयं इंजेक्ट करने के लिए आयात कर सकते हैं, तो उसके लिए एक DI लाइब्रेरी अच्छा है? चुना हुआ उत्तर सही है, क्योंकि जावा में कोई प्रक्रियात्मक खंड (कक्षाओं के बाहर कोड) नहीं है, जो सभी उबाऊ कॉन्फ़िगरेशन xml's में जाता है, इसलिए एक आलसी लोड फैशन पर निर्भरता को इंजेक्ट और इंजेक्ट करने के लिए एक वर्ग की आवश्यकता होती है ताकि आप उड़ा न दें। अपने प्रदर्शन, जबकि अजगर पर आप सिर्फ अपने कोड के "प्रक्रियात्मक" (कक्षाओं के बाहर कोड) वर्गों पर इंजेक्शन कोड करते हैं


आपको अभी भी याद है कि IoC / DI एक साथ वस्तुओं को स्वचालित रूप से तार करता है। यह रनटाइम के दौरान इसे करने में सक्षम नहीं है (जावा वैसे भी प्रतिबिंब के माध्यम से कर सकता है), यह है कि फ्रेमवर्क इसका ध्यान रखता है और आपको इसे स्पष्ट रूप से करने की आवश्यकता नहीं है। प्रक्रियात्मक खंड होने के कारण या तो अप्रासंगिक है, कुछ भी जावा में एक पूरी तरह से प्रक्रियात्मक ऐप लिखने के लिए नहीं रोकता है, कक्षाओं को स्थैतिक सबरूटीन्स और फ़ंक्शन के मात्र कंटेनरों के रूप में उपयोग करके, बिना ओओपी सुविधाओं का उपयोग किए बिना।
जक्कम

@ ज़ाकमेक: यहाँ पायथन का "प्रक्रियात्मक" खंड वास्तव में प्रक्रियात्मक कोड लिखने के बारे में नहीं है। स्थैतिक भाषाओं की तुलना में पायथन के "प्रक्रियात्मक" खंड को अलग बनाता है एक वर्ग निकाय में प्रक्रियात्मक कोड डालने की क्षमता है, जो कक्षा परिभाषा के समय के दौरान चलता है, और अगर-स्टेटमेंट के अंदर आयात विवरण डालता है, और केवल कक्षाओं को परिभाषित करके वर्ग कारखाना बनाने के लिए एक कारखाने विधि के अंदर। ये ऐसी चीजें हैं जो आप वास्तव में स्थिर भाषाओं में नहीं कर सकते हैं, और जो आईओसी / डीआई को हल करने की कोशिश की गई अधिकांश समस्याओं को हल करती है। पाइथन में मेटाप्रोग्रामिंग अक्सर नियमित पाइथन कोड की तरह दिखता है।
रेयान

@ लाइरेन, आप प्रतिबिंब के साथ ऐसा कर सकते हैं, या, यदि आपको अक्सर या रनटाइम पर इसकी आवश्यकता होती है, तो आप स्थैतिक भाषा को दूसरी भाषा जैसे ग्रूवी (जिसे आसानी से जावा के साथ खेलने के लिए डिज़ाइन किया गया है), या यहां तक ​​कि पायथन ही कह सकते हैं। फिर भी, इसका आईओसी / डीआई फ्रेमवर्क से बहुत कम लेना-देना है, क्योंकि उनका उद्देश्य आपके लिए अधिकतर प्रक्रियात्मक ऑब्जेक्ट वायरिंग करना है, स्वचालित रूप से, केवल परिभाषाओं पर लाभ उठाते हुए। अफसोस की बात है कि इसके अधिकांश उत्तर इस बिंदु को याद करते हैं।
जक्कम

12

कई सालों में अजगर का इस्तेमाल नहीं किया गया, लेकिन मैं कहूंगा कि इसका डायनेमिक टाइप की हुई भाषा के अलावा और कुछ भी नहीं है। एक सरल उदाहरण के लिए, जावा में, अगर मैं परीक्षण करना चाहता था कि कुछ लिखा गया है, तो मैं उचित रूप से डीआई का उपयोग कर सकता हूं और किसी भी प्रिंटस्ट्रीम में पास कर सकता हूं और लिखे गए पाठ को पकड़ने के लिए इसे सत्यापित कर सकता हूं। जब मैं रूबी में काम कर रहा हूं, हालांकि, मैं सत्यापित करने के लिए STDOUT पर 'पुट' विधि को गतिशील रूप से बदल सकता हूं, जिससे DI पूरी तरह से तस्वीर से बाहर हो जाएगा। यदि केवल एक कारण मैं अमूर्तता पैदा कर रहा हूं, तो उस वर्ग का परीक्षण करना है जो इसका उपयोग कर रहा है (विचार करें कि सिस्टम में फाइल या जावा में घड़ी) तो DI / IoC समाधान में अनावश्यक जटिलता पैदा करता है।


3
यह मुझे विस्मित करने के लिए कभी नहीं रोकता है कि लोग यह बदलने के लिए तैयार हैं कि एक प्रणाली यह परीक्षण करने के लिए कैसे काम करती है कि उसने काम किया। अब आपको परीक्षण करने की आवश्यकता है कि आपके परीक्षण दुष्प्रभाव का कारण नहीं हैं।
बेसिक

2
वह केवल परीक्षण के दायरे में पुट विधि को बदलने की बात करता है, यह इंजेक्शन वाली वस्तु की नकली विधि की तरह है।
dpa

2
@Basic यूनिट परीक्षणों में बहुत सामान्य है , वास्तव में यह करना उचित है कि इन परीक्षणों में आप कोड के एक से अधिक ब्लॉक (जो परीक्षण किया जा रहा है) के साथ अपने टेस्ट केस कवरेज को प्रदूषित नहीं करना चाहते हैं। यह करना गलत होगा कि एकीकरण परीक्षणों के लिए, हो सकता है कि आप अपनी टिप्पणी पर क्या उल्लेख कर रहे हैं?
samuelgrigolato

1
मेरे लिए, परीक्षणशीलता एक प्रथम श्रेणी की चिंता है। यदि कोई डिज़ाइन परीक्षण योग्य नहीं है, तो यह एक अच्छा डिज़ाइन नहीं है, और मुझे इसे अधिक परीक्षण योग्य बनाने के लिए डिज़ाइन को बदलने में कोई समस्या नहीं है। मुझे पुनर्विचार करना होगा कि यह अभी भी काम करता है, लेकिन यह ठीक है। कोड आईएमओ
कार्लोस रॉड्रिग्ज़

10

वास्तव में, यह काफी आसान पर्याप्त स्वच्छ और कॉम्पैक्ट कोड डि साथ (मैं आश्चर्य है, ठहरने यह हो जाएगा / लिखना है pythonic तो वैसे भी, लेकिन :)), उदाहरण के लिए मैं वास्तव में कोडिंग के इस तरह perefer:

def polite(name_str):
    return "dear " + name_str

def rude(name_str):
    return name_str + ", you, moron"

def greet(name_str, call=polite):
    print "Hello, " + call(name_str) + "!"

_

>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!

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

पीएस I ने भी पायथन में सरल बूलियन तर्क का मूल्यांकन करते हुए इस भोले दृष्टिकोण का एक बड़ा उदाहरण पोस्ट किया है


3
साधारण मामलों के लिए जो काम कर सकते हैं, लेकिन बस एक साधारण वेब ब्लॉग नियंत्रक की कल्पना करें, जो विभिन्न मॉडलों (पोस्ट, टिप्पणी, उपयोगकर्ता) का उपयोग करता है। यदि आप चाहते हैं कि उपयोगकर्ता अपने स्वयं के पोस्ट मॉडल (ट्रैक करने के लिए एक अतिरिक्त दृश्य विशेषता के साथ) को इंजेक्ट करें, और अधिक प्रोफ़ाइल जानकारी के साथ अपने स्वयं के उपयोगकर्ता मॉडल और इतने पर, सभी पैरामीटर भ्रामक लग सकते हैं। इसके अतिरिक्त, उपयोगकर्ता साधारण कुकी आधारित सत्र के बजाय फाइलसिस्टम सत्र का समर्थन करने के लिए अनुरोध वस्तु को भी बदलना चाह सकता है या ऐसा कुछ ... तो, आप शीघ्र ही बहुत सारे मापदंडों के साथ समाप्त हो जाएंगे।
tux21b

1
@ tux21b खैर, "आवश्यक जटिलता" है जो उपयोगकर्ता आवेदन को लागू करना चाहते हैं, इसके लिए वास्तु समाधान हैं (जिनमें से कुछ विकास और संभवतः रखरखाव समय, निष्पादन की गति, आदि के मामले में बाकी की तुलना में बदतर नहीं हैं) । ), और एपीआई और सॉफ्टवेयर आर्किटेक्चर को समझने की मानवीय क्षमता है। अगर कोई मानव-बोधगम्य समाधान नहीं है (केवल उन लोगों के बीच (किसी भी रूप में) DI का उपयोग नहीं कर रहा है) ... तो, किसने कहा कि सभी समस्याएं हल हैं? और बहुत सारे डिफ़ॉल्ट-असाइन किए गए (लेकिन उपयोगकर्ता की पसंद से स्वैपेबल) पैरामीटर वास्तव में अक्सर पर्याप्त हो सकते हैं।
mlvljr

9

IoC / DI एक डिजाइन अवधारणा है, लेकिन दुर्भाग्य से इसे अक्सर एक अवधारणा के रूप में लिया जाता है जो कुछ भाषाओं (या टाइपिंग सिस्टम) पर लागू होती है। मैं निर्भरता के इंजेक्शन के कंटेनर पाइथन में अधिक लोकप्रिय देखना पसंद करूंगा। स्प्रिंग है, लेकिन यह एक सुपर-फ्रेमवर्क है और लगता है कि "द पायथन वे" के लिए बहुत अधिक विचार किए बिना जावा अवधारणाओं का एक सीधा बंदरगाह है।

पायथन 3 में दिए गए एनोटेशन्स को देखते हुए, मैंने एक पूर्ण विशेषताओं पर एक दरार का फैसला किया, लेकिन सरल, निर्भरता इंजेक्शन कंटेनर: https://github.com/zsims/dic । यह एक .NET निर्भरता इंजेक्शन कंटेनर से कुछ अवधारणाओं पर आधारित है (जो IMO शानदार है यदि आप कभी भी उस स्थान पर खेल रहे हैं), लेकिन पायथन अवधारणाओं के साथ उत्परिवर्तित।


6

मुझे लगता है कि अजगर की गतिशील प्रकृति के कारण लोग अक्सर एक और गतिशील ढांचे की आवश्यकता नहीं देखते हैं। जब कोई वर्ग नई शैली की 'ऑब्जेक्ट' से विरासत में प्राप्त होता है तो आप एक नया चर गतिशील रूप से ( https://wiki.python.org/moin/NewClassVsClassicClass ) बना सकते हैं ।

अर्थात सादे अजगर में:

#application.py
class Application(object):
    def __init__(self):
        pass

#main.py
Application.postgres_connection = PostgresConnection()

#other.py
postgres_connection = Application.postgres_connection
db_data = postgres_connection.fetchone()

हालांकि https://github.com/noodleflake/pyioc पर एक नज़र है कि यह वही हो सकता है जिसे आप ढूंढ रहे हैं।

यानी पैयोक में

from libs.service_locator import ServiceLocator

#main.py
ServiceLocator.register(PostgresConnection)

#other.py
postgres_connection = ServiceLocator.resolve(PostgresConnection)
db_data = postgres_connection.fetchone()

2
बहुत तथ्य यह है कि दोनों संस्करण समान मात्रा में कोड लेते हैं, यह समझाने की दिशा में एक लंबा रास्ता तय करते हैं कि फ्रेमवर्क का उपयोग करना बहुत लोकप्रिय क्यों नहीं है।
स्पेक्ट्रा

में other.pyलाइन 1, वहाँ एक स्वचालित निर्भरता संकल्प है, लेकिन यह गिनती नहीं होगा एक निर्भरता इंजेक्शन हालांकि के रूप में।
औरो

सर्विस लोकेटर आमतौर पर एक विरोधी पैटर्न है, बस कह रहे हैं।
पैनासोनिक

6

मैं वापस "Jörg W Mittag" उत्तर देता हूं: "DI / IoC का पायथन कार्यान्वयन इतना हल्का है कि यह पूरी तरह से गायब हो जाता है"।

इस कथन का समर्थन करने के लिए, जावा से अजगर तक प्रसिद्ध मार्टिन फाउलर के उदाहरण पर एक नज़र डालें: अजगर: Design_Patterns: Inversion_of_Control

जैसा कि आप उपरोक्त लिंक से देख सकते हैं, पायथन में एक "कंटेनर" कोड की 8 पंक्तियों में लिखा जा सकता है:

class Container:
    def __init__(self, system_data):
        for component_name, component_class, component_args in system_data:
            if type(component_class) == types.ClassType:
                args = [self.__dict__[arg] for arg in component_args]
                self.__dict__[component_name] = component_class(*args)
            else:
                self.__dict__[component_name] = component_class

42
यह सबसे कमजोर DI कंटेनरों की तुलना में बहुत कम है। आजीवन प्रबंधन, पुनरावर्ती निर्भरता संकल्प, नकली करने की क्षमता, या - वह सब - असफलता कहाँ है? यह एक प्रकार के लुकअप और कैश से ज्यादा कुछ नहीं है जो IoC जैसी चीज नहीं है।
बेसिक

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

2

मेरा 2 सेंट यह है कि अधिकांश पायथन एप्लिकेशन में आपको इसकी आवश्यकता नहीं है और, यहां तक ​​कि अगर आपको इसकी आवश्यकता है, तो संभावना यह है कि कई जावा हैटर्स (और अक्षम फ़िडलर जो डेवलपर्स मानते हैं) इसे कुछ बुरा मानते हैं, सिर्फ इसलिए कि यह जावा में लोकप्रिय है ।

एक IoC प्रणाली वास्तव में उपयोगी होती है जब आपके पास वस्तुओं के जटिल नेटवर्क होते हैं, जहां प्रत्येक वस्तु कई अन्य लोगों के लिए एक निर्भरता हो सकती है और बदले में, स्वयं अन्य वस्तुओं पर निर्भर हो सकती है। ऐसे मामले में आप इन सभी वस्तुओं को एक बार परिभाषित करना चाहते हैं और संभव के रूप में कई निहित नियमों के आधार पर उन्हें स्वचालित रूप से एक साथ रखने के लिए एक तंत्र है। यदि आपके पास एप्लिकेशन उपयोगकर्ता / व्यवस्थापक द्वारा सरल तरीके से परिभाषित किया जाने वाला कॉन्फ़िगरेशन है, तो यह एक IoC सिस्टम की इच्छा करने का एक अतिरिक्त कारण है जो इसके घटकों को एक साधारण XML फ़ाइल (जो कॉन्फ़िगरेशन होगा) की तरह पढ़ सकता है।

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

उस ने कहा, पायथन परिस्थितियां हैं जहां आईओसी दृष्टिकोण वास्तव में उपयोगी है और वास्तव में, मैं यहां पढ़ता हूं कि Django इसका उपयोग करता है।

उपरोक्त तर्क को जावा दुनिया में एस्पेक्ट ओरिएंटेड प्रोग्रामिंग के लिए लागू किया जा सकता है, इस अंतर के साथ कि एओपी वास्तव में सार्थक होने वाले मामलों की संख्या और भी अधिक सीमित है।


क्या सूचना के स्रोत के लिए एक संदर्भ URL है जहाँ django IoC का उपयोग करता है?
सजुकुक २०'१

@ सज्जुक, मैंने सीखा है कि इस प्रश्न के थ्रेड पर Django के बारे में, इसलिए मुझे नहीं पता, आपको अन्य उत्तर लेखकों से पूछना चाहिए।
जक्कम

इस उत्तर के पहले एलिनिया ने मेरी राय में 0 मान जोड़ा है ... मुझे लगता है कि मैं यह तय करने में सक्षम हूं कि जब मेरे अजगर कोड IoC से लाभ होगा, और मुझे इस बात की परवाह नहीं है कि डेवलपर क्या सोचता है कि क्या बुरा है। मैं अपरिचित राय पर व्यावहारिकता को महत्व देता हूं।
माइक डी किलक

@MikedeKlerk मेरा सुझाव यह है कि कुछ ऐसा है जो दोनों अज्ञात है (जैसे कि कई उत्तर यहां साबित होते हैं) और पूर्वाग्रह का शिकार होने की संभावना नहीं है, चाहे आप कितने भी उद्देश्यपूर्ण और अच्छी तरह से अवगत हों। और निश्चित रूप से मुझे यकीन नहीं है कि यह एक कारण है कि आप पायथन में कई आईओसी का उपयोग क्यों नहीं करते हैं, मुझे लगता है कि मुख्य कारण कम / मध्यम संकलन एप्स की आवश्यकता नहीं है।
zakmck

The typical Python application is much simpler, just a bunch of scripts, without such a complex architecture.- काफी धारणा
हांकोव


-1

मैं @ जोर्ग के साथ इस बात से सहमत हूं कि पायथन में DI / IoC संभव, आसान और अधिक सुंदर है। जो चीज याद आ रही है, वह इसका समर्थन कर रही है, लेकिन कुछ अपवाद भी हैं। मेरे दिमाग में आने वाले कुछ उदाहरणों को इंगित करने के लिए:

  • Django टिप्पणी आप अपने कस्टम तर्क और रूपों के साथ अपने खुद के टिप्पणी वर्ग तार करते हैं। [और जानकारी]

  • Django आपको अपने उपयोगकर्ता मॉडल से जुड़ने के लिए एक कस्टम प्रोफ़ाइल ऑब्जेक्ट का उपयोग करने देता है। यह पूरी तरह से IoC नहीं है, लेकिन एक अच्छा तरीका है। व्यक्तिगत रूप से मैं होल यूजर मॉडल को बदलना चाहता हूं, जैसा कि टिप्पणी फ्रेमवर्क करता है। [और जानकारी]


-3

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

यह एक सांख्यिकीय-टाइप भाषा का लक्षण भी है। जब एकमात्र उपकरण आपको अमूर्तता व्यक्त करना है, तो विरासत है, तो आप हर जगह का उपयोग करते हैं। यह कहते हुए कि, C ++ काफी समान है, लेकिन कभी भी बिल्डरों और इंटरफेस के साथ आकर्षण को हर जगह नहीं उठाया है जो कि जावा डेवलपर्स ने किया था। बहुत ही वास्तविक लाभ के साथ बहुत अधिक सामान्य कोड लिखने की कीमत पर लचीला और एक्स्टेंसिबल होने के सपने के साथ अतिउत्साहित होना आसान है । मुझे लगता है कि यह एक सांस्कृतिक चीज है।

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


4
यह इतना ढांचा नहीं है जितना कि भाषा। जिस प्रकार का लचीलापन डक-टाइपिंग भाषाओं का आनंद लेता है, उसे बनाने के लिए, सांख्यिकीय रूप से टाइप की गई भाषाओं को बहुत परिष्कृत रूपरेखा और नियमों की आवश्यकता होती है। DI उन नियमों में से एक है। अजगर लोगों के बारे में दो बार नहीं सोचते हैं। जावा लोगों को वास्तव में इस पर काम करना होगा।
एस.लॉट

6
@ एस.लॉट - मैं पूरी तरह से आपके साथ सहमत हूं, सिवाय इसके कि जावा के समान प्रतिबंधों के साथ काम करने के बावजूद सी ++ लोग डिजाइन और वास्तुकला पैटर्न के विस्फोट के बिना प्राप्त करते हैं। मुझे लगता है कि एक सांस्कृतिक अंतर का तात्पर्य है, जहां कुछ करने के लिए 2 संभावित तरीकों का सामना करने पर, जावा लोग रणनीति पैटर्न को सुविधाजनक बनाने के लिए एक और इंटरफ़ेस निकालना पसंद करते हैं, जबकि C ++ लोग सही तरीके से डुबकी लगाते हैं और एक बूल जोड़ते हैं और यदि एक बयान ...
कियलोतन

3
@Finglas अगर मेरे पास एक दर्जन कक्षाएं हैं जो मेरे उपयोग से हैं EmailSenderऔर इसे एक के साथ बदलने का फैसला किया है DesktopNotifier, तो मुझे 12 कक्षाओं को हाथ से संपादित करना होगा। और आपको लगता है कि यह सरल और साफ है कि सिर्फ एक INotifierइंटरफेस के लिए लिख रहा है और कंटेनर को विवरण देने का काम कर रहा है?
बेसिक

1
दुर्भाग्य से, जटिलता का एक निश्चित स्तर एक वास्तविकता है जिसे पेशेवर सॉफ़्टवेयर डेवलपर्स को सामना करना होगा। मैं आलोचनाओं को देखता हूं लेकिन इस जवाब में कोई समाधान नहीं है। इस समस्या के लिए "पायथोनिक" समाधान क्या है: मैं एक पुस्तकालय लिख रहा हूं और मैं लॉगिंग के लिए एक हुक प्रदान करना चाहता हूं (PHP के PSR-3 LoggerInterface जैसा कुछ)। मुझे पता है कि लॉग स्तरों का उपयोग कैसे किया जाता है, लेकिन मुझे परवाह नहीं है कि कार्यक्रम वास्तव में उन्हें कैसे रिपोर्ट करता है। क्लाइंट एप्लिकेशन को उस कार्यान्वयन विवरण को इंजेक्ट करने की अनुमति देने का स्वच्छ तरीका क्या है । नोट: अनुप्रयोग के अन्य भागों में इस इंटरफ़ेस के अलग-अलग कार्यान्वयन हो सकते हैं।
रॉब

2
आपके लिए मेरा सवाल यह नहीं है कि आप मानक लॉगिंग लाइब्रेरी का उपयोग कैसे करते हैं, न ही यह एक लकड़हारे वर्ग के विभिन्न उदाहरण बनाने के बारे में है। मेरा प्रश्न यह है कि आप अपने आवेदन को कैसे कॉन्फ़िगर करते हैं ताकि आपके आवेदन के विभिन्न हिस्से अलग-अलग कार्यान्वयन का उपयोग कर सकें, और उन विवरणों से चिंतित न हों (बशर्ते कि वे इंटरफ़ेस का उपयोग करना जानते हों)। यह एक बहुत ही वास्तविक समस्या है जिसे DI ने मेरे द्वारा काम किए गए कई PHP अनुप्रयोगों के लिए हल किया है। मैं अजगर के बराबर देख रहा हूँ। और सुझाव देते हुए "बस अपने आवेदन को जटिल मत बनाओ" वह उत्तर नहीं है जिसकी मुझे तलाश है।
राब

-5

जावा में मजबूत टाइप प्रकृति के विपरीत। अजगर के बत्तख टाइप व्यवहार के कारण वस्तुओं को पास करना इतना आसान हो जाता है।

जावा डेवलपर्स चीजों के लचीलेपन को बनाए रखते हुए वर्ग स्ट्रैचिंग और ऑब्जेक्ट्स के बीच संबंध बनाने पर ध्यान केंद्रित कर रहे हैं। इसे प्राप्त करने के लिए आईओसी अत्यंत महत्वपूर्ण है।

पायथन डेवलपर्स काम पूरा करने पर ध्यान केंद्रित कर रहे हैं। वे बस कक्षाओं को तार करते हैं जब उन्हें इसकी आवश्यकता होती है। वे भी वर्ग के प्रकार के बारे में चिंता करने की ज़रूरत नहीं है। जब तक यह शांत हो सकता है, यह एक बतख है! यह प्रकृति IoC के लिए कोई जगह नहीं छोड़ती है।


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