【问题标题】:Compare types in Python比较 Python 中的类型
【发布时间】:2021-03-03 04:03:08
【问题描述】:

我正在构建用于动态加载模块的基础架构。每个模块都应该包含一个继承自同一个基类的类。

模块的结构是这样的:

app
\- vendors
 \- __init__.py
 \- vendor_base.py
 \- vendor1.py
 \- vendor2.py
...

__init__.py:

from .vendor_base import VendorBase
self = sys.modules[__name__]
__all__ = []
vendors = []
modules = [ f
    for f in glob.glob(join(dirname(__file__), "*.py"))
    if isfile(f) and not f.endswith('__init__.py')
]
for module in modules:
    with open(module, 'rb') as fp:
        module_name = splitext(basename(module))[0]
        ma = imp.load_module(
            'app.vendors.' + module_name, 
            fp, basename(module), ('.py', 'r', imp.PY_SOURCE)) 
        classes = { c for c in ma.__dict__.items() 
            if isinstance(c[1], type) and issubclass(c[1], VendorBase) }
        for class_pair in classes:
            setattr(self, class_pair[0], class_pair[1])
            if class_pair[0] not in __all__:
                __all__.append(class_pair[0])
                if issubclass(class_pair[1], VendorBase):
                    vendors.append(class_pair[1])

vendor_base.py:

from abc import ABCMeta, abstractmethod

class VendorBase(metaclass=ABCMeta):
    @classmethod
    def __subclasshook__(cls, subclass):
        return subclass is not cls and cls in subclass.__mro__

    @abstractmethod
    def post_purchase_order(self, purchase_order):
        pass

vendor1.py:

from . import VendorBase

class Vendor1(VendorBase):
    def post_purchase_order(self, purchase_order):
        pass

vendor2.py:

from . import VendorBase

class Vendor2(VendorBase):
    def post_purchase_order(self, purchase_order):
        pass

所以我希望类 Vendor1 和 Vendor2 被加载并在模块 app.vendors 中可用(在 __all__vendors 中)。但是它们没有加载。我检查了 VendorBase.__subclasshook__() 中的类比较没有按预期工作。

当我运行issubclass(VendorBase, Vendor1) 时,我得到False。此外,即使在调试器VendorBase.__subclasshook__(cls, subclass) 中:

cls

'app.vendors.vendor_base.VendorBase'>

子类

'app.vendors.vendor_base.VendorBase'>

我检查cls is subclass 我仍然得到False。 我虽然它可能与供应商类模块中不同的导入基类名称有关。所以我确保VendorBase 是从vendors 导入的,它也被使用。但似乎仍然有不同的类实例。

【问题讨论】:

  • 您正在寻找isinstance()。 Python 中的is 是身份检查; 1 is int 返回False
  • 您可能只想使用入口点而不是滚动您自己的加载程序...packaging.python.org/guides/creating-and-discovering-plugins/…
  • 回复issubclass(VendorBase, Vendor1)。你的论点倒过来了。
  • @Flair 我相信isinstance() 适用于对象。我在比较类(不是对象)
  • @AKX 每次添加插件时不需要重新运行设置吗?这个想法是,只要将文件放入目标目录,就会加载新模块

标签: python class vendor


【解决方案1】:

您已经在使用模块 imp 进行加载,然后也使用它来查找。

imp.find_module(name[, path])

请发布进展情况

【讨论】:

  • 对不起,我不明白查找模块是如何相关的
  • 首先是它是pythonic方式。既然有可用的测试代码,为什么还要自己编写代码。
  • 我还是不明白这和问题有什么关系。
猜你喜欢
  • 2018-01-21
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 2011-09-03
  • 2010-10-16
  • 2023-01-13
  • 2023-03-26
  • 1970-01-01
相关资源
最近更新 更多