在Python中使用Inheritence时,我有一个有趣的导入错误。
在父类中我导入模块sqlite3,在子类中我然后尝试使用sqlite3函数,但是我收到一条错误,说“NameError:全局名称'sqlite3'未定义”。 为什么会发生这种情况?我该如何解决?
这两个类位于不同的文件中:
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()
答案 0 :(得分:16)
将sqlite3模块导入父模块,因此您需要通过该模块访问它
self.db = Parent.sqlite3.connect("test.db")
除非告诉python这样做,否则它不会直接导入Child模块,例如
from Parent import *
将允许您从子模块
中访问父模块的所有成员答案 1 :(得分:7)
子进程拥有自己的命名空间,并且没有将sqlite3导入其中。所以你需要将sqlite3导入Child.py。您也可以import Parent.sqlite3
,然后拨打Parent.sqlite3.connect
。这样做并没有真正的优势,而不是仅仅导入sqlite3,因为模块实际上只导入一次(在代码到达的第一次导入时),以下导入只是将模块添加到当前命名空间。
答案 2 :(得分:2)
您尚未将sqlite3
模块导入Parent
类(您可以,但这可能会非常奇怪)。您已将sqlite3
导入Parent.py
模块,其中包含Parent
类,并在其定义中使用sqlite3
模块。
然后一个单独的模块导入Parent.py
模块,并定义Parent
的子类。这不会自动将Parent
类中的所有内容都纳入范围[1],当您在Parent
中定义Parent.py
类时,它肯定不会带来范围内的所有内容进入范围。如果您在Parent.py
中声明了其他类,那么您不会期望这些名称在Child
中的范围内,因为它们与其父类位于同一模块中,所以为什么您会期望这个?恰好用于定义一些Parent
方法的模块?
您已经引用了导入sqlite3
的命名空间;当你说Parent
时,为了对它进行子类化,你得到了class Child(Parent.Parent)
类。所以你可以使用Parent.sqlite3
访问sqlite3
,但这是在Python中使用模块的一种非常奇怪的方式。
通常情况下,只需将import sqlite3
添加到Child.py
的顶部即可。然后阅读代码的任何人都会看到它使用sqlite3
。如果您使用从sqlite3
导入的Parent.py
看到您,他们会想知道您为什么不使用正常方式,并认为您可能正在做一些棘手的事情,比如包裹{{1}你添加了一些额外代码的模块。如果你刚刚完成了sqlite3
,那么 import * from Parent
这个名字来自哪里,你的读者真的会感到困惑。当您决定不需要在sqlite3
中导入sqlite3
时,您的代码将神秘地停止工作,但错误消息不会告诉您有关Parent.py
的任何信息。
一般来说,如果您正在做一些简单明显的事情,例如导入标准模块,您应该以简单明了的方式进行。人们习惯于阅读它,并且很容易接受它,而不需要停下来思考它。最容易出问题的“迷茫的读者”就是在几个月内你自己忘记了这段代码的确切运作方式;当你想要再次搞清楚时,你想让自己尽可能轻松。
[1]从父类继承与范围没有任何关系,即您可以访问哪些名称而无需限定它们。您无法访问定义子类的类块中的父类的方法和类变量。这意味着在创建子类之后,如果在子类中找不到内容,则实例的名称解析协议和类变量将在Parent中查找。这是一个有点微妙的点,基本归结为子类块中的(1)(包括方法的定义)Parent.py
会给你一个错误,但是(2)子类存在之后(包括方法实际上运行)some_parent_method()
(或方法中的Child.some_parent_method()
)将找到父方法。