2012-12-13 20 views
7

एक तरीका है "से" कीवर्ड का उपयोग किये बिना आयात एक्स का उपयोग करना। तो फिर आप चीजों को उनके नामस्थान के साथ हर जगह संदर्भित करते हैं।पायथन में परिपत्र (चक्रीय) आयात से बचें?

क्या कोई अन्य तरीका है? सी ++ ifnotdef __b__ def __b__ चीज़ की तरह कुछ करने की तरह?

+2

सर्कुलर निर्भरताएं नहीं हैं, वाई में एक्स की निर्भरताओं को जोड़कर जेड बनाएं, और x – Esailija

+0

में y की निर्भरताएं यह पोस्ट एक डुप्लिकेट है: http://stackoverflow.com/questions/744373/circular-or-cyclic -इम्पोर्ट्स-इन-पायथन – alinsoar

+1

@ एलिनसॉर यह एक सटीक डुप्लिकेट नहीं है - उस प्रश्न से पूछा गया कि आपके पास परिपत्र आयात कब होता है; और यह सवाल उनसे बचने के लिए तकनीकों के लिए पूछता है। –

उत्तर

10

मॉड्यूल की किसी भी जोड़ी को एक दूसरे पर एक-दूसरे पर निर्भर करते हुए मर्ज करें। फिर पुराने नाम वापस पाने के लिए अतिरिक्त मॉड्यूल पेश करें।

जैसे,

# a.py 
from b import B 

class A: whatever 

# b.py 
from a import A 

class B: whatever 

हो जाता है

# common.py 
class A: whatever 
class B: whatever 

# a.py 
from common import A 

# b.py 
from common import B 
+0

मुझे लगता है कि आपको 'सामान्य आयात ए' से और 'सामान्य आयात बी' से करना था? – jdi

+0

@jdi: हाँ। धन्यवाद, इसे ठीक किया। –

+21

यह किसी को 'a.py' और' b.py' की बजाय 'common.py' में सबकुछ घोषित करना शुरू कर देता है। आईएमएचओ का अच्छा समाधान नहीं है। – Nick

5

परिपत्र आयात एक हैं "कोड गंध," और अक्सर (लेकिन हमेशा नहीं) संकेत मिलता है कि कुछ रिफैक्टरिंग उपयुक्त होगा। उदा।, A.xB.y और B.y का उपयोग A.z का उपयोग करता है, तो आप A.z को अपने मॉड्यूल में ले जाने पर विचार कर सकते हैं।

आप आप परिपत्र आयात की जरूरत है, तो मैं आम तौर पर मॉड्यूल आयात और पूरी तरह से योग्य नाम हैं (यानी, import A और A.x बजाय from A import x का उपयोग करें) के साथ वस्तुओं की चर्चा करते हुए सलाह देते हैं।

+1

क्या होगा अगर कोई कुछ स्पष्ट प्रकार की जांच कर रहा है? मैं अभी ऐसा करने की कोशिश कर रहा हूं, इसलिए मैं कुछ अप्रचलित ट्रेसबैक की बजाय एक बहुत विस्तृत त्रुटि संदेश प्रदान कर सकता हूं, जो कि मेरे ग्राहक समझ में नहीं आते हैं। – Nick

0

यदि आप from A import * करने का प्रयास कर रहे हैं, तो उत्तर बहुत आसान है: ऐसा मत करें।करने के लिए आमतौर पर माना जाता है और योग्य नामों का संदर्भ लें।

त्वरित & गंदे स्क्रिप्ट, और इंटरैक्टिव सत्रों के लिए, यह करने के लिए एक पूरी तरह से उचित बात है- लेकिन ऐसे मामलों में, आप परिपत्र आयात में नहीं भागेंगे।

कुछ ऐसे मामले हैं जहां वास्तविक कोड में import * करना समझ में आता है। उदाहरण के लिए, यदि आप जटिल मॉड्यूल संरचना को छिपाना चाहते हैं, या जो आप गतिशील रूप से उत्पन्न करते हैं, या जो संस्करणों के बीच अक्सर बदलते हैं, या यदि आप किसी और के पैकेज को लपेट रहे हैं जो बहुत गहराई से घोंसला है, तो import * "रैपर" से समझ सकता है मॉड्यूल "या एक शीर्ष स्तरीय पैकेज मॉड्यूल। लेकिन उस स्थिति में, आपके द्वारा आयात किए जाने वाले कुछ भी आपको आयात नहीं करेंगे।

वास्तव में, मुझे किसी भी मामले की कल्पना करने में कठिनाई हो रही है जहां import * वारंट है और परिपत्र निर्भरता भी एक संभावना है।

यदि आप from A import foo कर रहे हैं, तो इसके आसपास के तरीके हैं (उदाहरण के लिए, import A फिर foo = A.foo)। लेकिन आप शायद ऐसा नहीं करना चाहते हैं। दोबारा, इस बात पर विचार करें कि आपको अपने नामस्थान में foo लाने की ज़रूरत है-योग्य नाम एक विशेषता है, न कि आसपास काम करने की समस्या है।

आप बस अपने कार्यों को लागू करने में सुविधा के लिए from A import foo कर रहे हैं, क्योंकि A वास्तव में long_package_name.really_long_module_name है और अपने कोड क्योंकि long_package_name.really_long_module_name.long_class_name.class_method_that_puts_me_over_80_characters करने के लिए उन सभी कॉल्स के पढ़ने योग्य नहीं है, याद है कि आप हमेशा import long_package_name.really_long_module_name as P और फिर आप योग्य के लिए P उपयोग कर सकते हैं कहता है।

(यह भी ध्यान रखें कि किसी भी from कार्यान्वयन की सुविधा के लिए किया साथ, तो आप शायद करने के लिए एक __all__ निर्दिष्ट करने के लिए यह सुनिश्चित करना चाहते यकीन है कि आयातित नाम अपने नाम स्थान का हिस्सा बनने के प्रकट नहीं होते हैं अगर कोई आप पर एक import * करता है एक इंटरैक्टिव सत्र से।)

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

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