Python子项不能使用父项导入的模块

时间:2012-01-22 00:04:56

标签: python inheritance import polymorphism

在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()

3 个答案:

答案 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())将找到父方法。