用元类实现Python工厂模式

2024-06-01 00:56:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我在实现一个易于使用的抽象工厂时遇到了一些问题。在

目标

为了能够这样定义混凝土工厂:

class MyConcreteFactory( ... ):
    @classmethod
    def __load(cls, key):
        obj = ... # Loading instructions here
        return obj

能够以这种方式使用混凝土工厂

^{pr2}$

我的尝试

我试图为factories定义一个元类,它覆盖了方括号操作符并封装了factory模式:

class __FactoryMeta(type):

    __ressources = {}

    @classmethod
    def __getitem__(cls, key):
        if key not in cls.__ressources:
            cls.__ressources[key] = cls.__load(key)
        return cls.__ressources[key]

    @classmethod
    def __load(cls, key):
        raise NotImplementedError


class ConcreteFactory(metaclass=__FactoryMeta):

    @classmethod
    def __load(cls, key):
        return "toto"


a = ConcreteFactory["mykey"]
print(a)

发行

这失败了,因为调用的\uyu load方法是来自元类的方法,而不是来自具体类的方法。结果是:

Traceback (most recent call last):
  File "C:\Users\walter\workspace\Game\src\core\factories.py", line 34, in <module>
    a = ConcreteFactory["mykey"]
  File "C:\Users\walter\workspace\Game\src\core\factories.py", line 19, in __getitem__
    cls.__ressources[key] = cls.__load(key)
  File "C:\Users\walter\workspace\Game\src\core\factories.py", line 24, in __load
    raise NotImplementedError
NotImplementedError

我试图从元类中删除\uuuLoad方法,但是我得到了一个(可预测的)错误:

Traceback (most recent call last):
  File "C:\Users\walter\workspace\Game\src\core\factories.py", line 30, in <module>
    a = ConcreteFactory["mykey"]
  File "C:\Users\walter\workspace\Game\src\core\factories.py", line 19, in __getitem__
    cls.__ressources[key] = cls.__load(key)
AttributeError: type object '__FactoryMeta' has no attribute '_FactoryMeta__load'

问题

有没有从元类访问类方法的方法? 我错了,应该换一种方式来做吗?那么威奇路?在

解决方案

class __FactoryMeta(type):

    ressources = {}

    def __getitem__(cls, key):
        if key not in cls.ressources:
            cls.ressources[key] = cls.load(key)
        return cls.ressources[key]

    def load(cls, key):
        raise NotImplementedError


class ConcreteFactory(metaclass=__FactoryMeta):

    @classmethod
    def load(cls, key):
        return "toto"


a = ConcreteFactory["mykey"]
print(a)

Tags: 方法keyinreturndefloadusersclass
1条回答
网友
1楼 · 发布于 2024-06-01 00:56:45

您不应该在元类中使用@classmethod。元类的一个实例是类本身,因此:

def __getitem__(cls, key):

实际上是班级和:

^{pr2}$

获取元类作为第一个参数。在

在另一个例子中,我相信元类使这个问题更加复杂。我相信一个更可行的方法是创建一个基工厂类,相应地将其子类化,并使用子类的实例作为工厂。在

相关问题 更多 >