2012-01-22 11 views
7

पाइथन में विरासत का उपयोग करते समय मुझे एक मजेदार आयात त्रुटि है।पाइथन चाइल्ड एक मॉड्यूल का उपयोग नहीं कर सकता है जो माता-पिता आयातित

एक अभिभावक वर्ग में मैं एक वर्ग वर्ग में मॉड्यूल sqlite3 आयात करता हूं, फिर एक sqlite3 फ़ंक्शन का उपयोग करने का प्रयास करता हूं लेकिन मुझे "नाम त्रुटि: वैश्विक नाम 'sqlite3' परिभाषित नहीं किया गया है"। ऐसा क्यों होता है & मैं इसे कैसे ठीक करूं?

2 वर्गों अलग फ़ाइलें हैं:

Parent.py

import sqlite3 

class Parent: 
    def __init__(self): 

     self.create_database() 

    def create_database(self): 
     """ Virtual function to be overriden in child classes """ 
     pass 

    ...more class functions that use sqlite3 functions 

Child.py

import Parent 

class Child(Parent.Parent): 
    def create_database(self): 
     self.db = sqlite3.connect("test.db") # Error occurs HERE 

c = Child() 

उत्तर

12

sqlite3 मॉड्यूल जनक मॉड्यूल में आयात किया जाता है, इसलिए आपको लगता है कि मॉड्यूल के माध्यम से इसे उपयोग करने की जरूरत है

self.db = Parent.sqlite3.connect("test.db") 

यह सीधे, बाल मॉड्यूल में आयात नहीं कर रहा है जब तक आप ऐसा करने के लिए अजगर बता उदाहरण

के लिए
from Parent import * 

आप बाल मॉड्यूल के भीतर से

+1

या बस बाल मॉड्यूल पर 'आयात sqlite3' का उपयोग करें। – jsbueno

+1

पृथ्वी पर क्यों आप माता-पिता के माध्यम से sqlite3 तक पहुंचेंगे? इसके अलावा, "आयात *" बहुत अच्छा नहीं है। –

+1

सहमत हैं, यह स्वीकार करने का एक बुरा जवाब है - 'आयात sqlite3'' ऐसा करने का सही तरीका है। –

5

बच्चे अपने स्वयं के नाम स्थान है और आप sqlite3 आयात नहीं किया है इसे में। तो आपको Child.py में sqlite3 आयात करने की आवश्यकता है। आप import Parent.sqlite3 भी कर सकते हैं और फिर Parent.sqlite3.connect पर कॉल कर सकते हैं। स्क्लाइट 3 आयात करने की बजाय इसे करने के लिए इसका कोई वास्तविक लाभ नहीं है, क्योंकि मॉड्यूल केवल एक बार वास्तव में आयात किए जाते हैं (कोड आयात करने वाले पहले आयात पर) और निम्न आयात केवल मॉड्यूल को वर्तमान नेमस्पेस में जोड़ते हैं।

2

आपआयात नहीं किया है जनक मॉड्यूल के सभी सदस्यों तक पहुँच प्रदान करेगा Parent कक्षा मेंमॉड्यूल (आप कर सकते हैं, लेकिन यह वास्तव में अजीब होगा)। आपने को Parent.pyमॉड्यूल में आयात किया है, जिसमें Parent कक्षा शामिल है, और इसकी परिभाषा में sqlite3 मॉड्यूल का उपयोग करता है।

फिर एक अलग मॉड्यूल Parent.py मॉड्यूल आयात करता है, और Parent के उप-वर्ग को परिभाषित करता है। यह स्वचालित रूप से Parent वर्ग में सबकुछ को दायरे में नहीं लाता है [1], और यह निश्चित रूप से कक्षा Parent.py को दायरे में परिभाषित करते समय सब कुछ नहीं लाता है। यदि आपने अन्य कक्षाओं को Parent.py में घोषित किया है, तो आप उम्मीद नहीं करेंगे कि उन नामों को Child में गुंजाइश में रहने की उम्मीद है क्योंकि वे अपने मूल वर्ग के समान मॉड्यूल में थे, तो आप इस मॉड्यूल की अपेक्षा क्यों करेंगे जो बस उपयोग में होता है Parent के तरीकों को परिभाषित करना?

आपके पास पहले से ही नामस्थान का संदर्भ है जहां sqlite3 आयात किया गया था; class Child(Parent.Parent) पर कहा गया था कि आपको Parent कक्षा से बाहर निकालने के लिए इसे उपclass करने के लिए मिला है। तो Parent.sqlite3 का उपयोग sqlite3 तक पहुंचने के लिए कर सकता है, लेकिन यह पायथन में मॉड्यूल का उपयोग करने का एक बहुत ही अजीब तरीका है।

आम तौर पर Child.py के शीर्ष पर import sqlite3 जोड़ने के लिए बेहतर है। फिर कोड पढ़ने वाला कोई भी व्यक्ति देखेगा कि यह sqlite3 का उपयोग करता है।यदि आप sqlite3 का उपयोग करते हुए देखते हैं कि आपने Parent.py से आयात किया है, तो वे आश्चर्यचकित होंगे कि आपने सामान्य तरीके का उपयोग क्यों नहीं किया है, और लगता है कि आप कुछ अतिरिक्त कोड के साथ sqlite3 मॉड्यूल को लपेटने जैसी कुछ मुश्किल कर रहे हैं। और यदि आपने अभी import * from Parent किया है, तो यह भी स्पष्ट नहीं है जहांsqlite3 नाम आया था, और आपके पाठक वास्तव में उलझन में होंगे। और जब आपका निर्णय में आयात करने की आवश्यकता नहीं है, तो आपका कोड रहस्यमय तरीके से काम करना बंद कर देगा, लेकिन त्रुटि संदेश आपको Parent.py के बारे में कुछ भी नहीं बताएगा।

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


[1] एक माता पिता के वर्ग से विरासत गुंजाइश, के साथ क्या करना बिल्कुल कुछ भी नहीं है अर्थात क्या नाम आप उन्हें योग्यता के बिना उपयोग कर सकते हैं। आपको कक्षा वर्ग परिभाषित कक्षा ब्लॉक के अंदर पैरेंट क्लास 'विधियों और कक्षा चर तक पहुंच प्राप्त नहीं है। इसका अर्थ यह है कि बाल वर्ग के निर्माण के बाद, उदाहरण के लिए नाम संकल्प प्रोटोकॉल माता-पिता में दिखाई देगा यदि उन्हें बाल वर्ग में चीजें नहीं मिलती हैं। यह कुछ हद तक सूक्ष्म बिंदु है, जो मूल रूप से बाल वर्ग ब्लॉक (विधियों की परिभाषाओं सहित) के भीतर (1) तक उबाल जाता है some_parent_method() आपको एक त्रुटि देगा, लेकिन (2) बाल वर्ग मौजूद होने के बाद (जब विधियां वास्तव में चलती हैं) Child.some_parent_method() (या self.some_parent_method() किसी विधि के भीतर) माता-पिता की विधि पायेगा।