Python абстрактные базовые классы - PullRequest
0 голосов
/ 27 мая 2018

По мере того, как я углубляюсь во внутренности Python, я начинаю чаще видеть abc в документации.К сожалению, документы не объясняют, как их можно использовать.Я даже не смог использовать «конкретные реализации» этих абстрактных базовых классов.

Например, читая о классе importlib.abc.SourceLoader, вы узнаете, что is_package является конкретной реализацией InspectLoader.is_package ().Но что если я хотел бы использовать это в своем коде?Является ли это возможным?Я пробовал много способов, но метод не может быть импортирован.

ExtensionFileLoader задокументирован как конкретная реализация importlib.abc.ExecutionLoader, но если я попытаюсь его использовать (например, из 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» задокументирован как конкретный, поэтому я должен иметь возможность каким-то образом его использовать, и это мой вопрос.

1 Ответ

0 голосов
/ 27 мая 2018
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, я считаю, что они имеют в виду, что SourceLoader обеспечивает реализацию по умолчанию для is_package, так что его подклассам не нужно переопределять его, чтобыбыть неабстрактным.)

Следовательно, вам нужно написать:

from importlib.machinery import SourceFileLoader

...

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

, где fullname - это «полностью разрешенное имя модуля, который должен обрабатывать загрузчик» и path - это «путь к файлу для модуля».

...