【问题标题】:Python abstract base classesPython 抽象基类
【发布时间】:2018-11-06 08:38:00
【问题描述】:

随着我对 Python 内部结构的深入研究,我开始在文档中更频繁地看到 abc。不幸的是,文档没有解释如何使用它们。我什至无法使用这些抽象基类的“具体实现”。

例如,阅读有关 importlib.abc.SourceLoader 类的信息,您会了解到“is_package”是 InspectLoader.is_package() 的具体实现。但是如果我想在我的代码中使用它呢?可能吗?我尝试了很多方法,但方法无法导入。

ExtensionFileLoader 被记录为 importlib.abc.ExecutionLoader 的具体实现,但如果我尝试使用它(例如:from importlib import Machinery.ExecutionLoader),再次找不到它。

如果这些方法无法导入,为什么要记录它们?是否有任何示例代码来显示如何使用它们?示例:

import importlib.abc.SourceLoader     # doesn't work

class try_pkg_check():

    def main(self, source_file_name):   
        possible_pkgs = ['math', 'numpy']           
        for posbl_pkg in possible_pkgs:         
            answer = SourceLoader.is_package(posbl_pkg)            
            print("For {}, the answer is: {}".format(posbl_pkg, answer))                
        return None         

if __name__ == "__main__":    
    instantiated_obj = try_pkg_check()      
    instantiated_obj.main()

人们可能会评论说我不应该尝试导入抽象类。但是“is_package”被记录为具体的,所以我应该能够以某种方式使用它,这是我的问题。

【问题讨论】:

  • importlib.abc.ExecutionLoaderimportlib.abc 中,但from importlib import machinery.ExecutionLoader 假定它在importlib.machinery 中。
  • 实际上,from importlib import machinery.ExecutionLoader 是无效的语法,因此您会得到与“无法找到”不同的错误。您能否向我们展示一些您尝试运行但未达到您预期的实际代码?
  • 您的问题是以 abc 和 ExecutionLoader 为例,还是您了解 abc 并想了解有关 ExecutionLoader6 的更多详细信息
  • 一旦我学会了如何防止在发布代码时删除换行符,我就会发布代码。阅读帮助文档但没有看到它被提及,这很奇怪,因为它应该是第一个涵盖的主题。

标签: python abstract-class abc


【解决方案1】:
import importlib.abc.SourceLoader

此行产生的错误消息应该会提示您出错的地方:

ModuleNotFoundError: No module named 'importlib.abc.SourceLoader'; 'importlib.abc' is not a package

"import foo" 要求 foo 是一个模块,但 SourceLoader 是一个模块内的类。您需要改为:

from importlib.abc import SourceLoader

但是,这行还有其他问题:

answer = SourceLoader.is_package(posbl_pkg)

首先SourceLoader.is_package是实例方法,不是类或静态方法;它必须在SourceLoader 的实例上调用,而不是在类本身上。但是SourceLoader是一个抽象类,所以不能直接实例化;你需要使用像SourceFileLoader 这样的具体子类。 (当文档将SourceLoader.is_package 称为InspectLoader.is_package 的“具体实现”时,我相信他们的意思是SourceLoaderis_package 提供了一个默认实现,因此它的子类不需要重写它以是非抽象的。)

因此,你需要写:

from importlib.machinery import SourceFileLoader

...

answer = SourceFileLoader(fullname, path).is_package(fullname)

其中fullname 是“加载程序要处理的模块的完全解析名称”,path 是“模块文件的路径”。

【讨论】:

    猜你喜欢
    • 2018-07-11
    • 2016-07-05
    • 2011-02-21
    • 2020-04-03
    • 2011-06-15
    • 2012-04-03
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    相关资源
    最近更新 更多