Python:将派生类转换为单例

Python:将派生类转换为单例,python,Python,我想将我的派生类转换成python中的单例。我希望通过元类实现singleton,但我总是遇到以下错误: TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases 我的代码: # singleton.py class Singleton(type): _instances = {}

我想将我的派生类转换成python中的单例。我希望通过元类实现singleton,但我总是遇到以下错误:

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
我的代码:

# singleton.py
class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

# base.py
from abc import ABC, abstractmethod

class Base(ABC):
    @abstractmethod
    def run(self, value):
        pass

# foo.py
from base import Base
from singleton import Singleton

class Foo(Base, metaclass=Singleton):
    def run(self, value):
        print(value)

# main.py
from foo import Foo

f1 = Foo()
print(f1)
f1.run(42)
f2 = Foo()
print(f2)
f2.run(24)

通过其他各种问题,我现在自己想出了一个解决办法

如错误文本所述,
Foo
的元类必须是与基类元类(
ABCMeta
)兼容的元类。 这意味着
Singleton
也必须继承自
ABCMeta

新代码:

# singleton.py

from abc import ABCMeta

class Singleton(ABCMeta):
    # ...

# bar.py
from base import Base

class Bar(Base):
    def run(self, value):
        print(value)

# main.py
from foo import Foo
from bar import Bar

f1 = Foo()
print(f1)
f1.run(42)
f2 = Foo()
print(f2)
f2.run(34)

b1 = Bar()
print(b1)
b1.run(12)
b2 = Bar()
print(b2)
b2.run(21)
输出:

<foo.Foo object at 0x000001D4D512BE48>
42
<foo.Foo object at 0x000001D4D512BE48>
34
<bar.Bar object at 0x000001D4D512B0B8>
12
<bar.Bar object at 0x000001D4D512BEF0>
21

42
34
12
21
因此,
Foo
是一个单例,而
Bar
不是

奖金问题:


为什么单例(ABC)不起作用?

通过各种其他stackoverflow问题,我现在自己想出了一个解决方案

如错误文本所述,
Foo
的元类必须是与基类元类(
ABCMeta
)兼容的元类。 这意味着
Singleton
也必须继承自
ABCMeta

新代码:

# singleton.py

from abc import ABCMeta

class Singleton(ABCMeta):
    # ...

# bar.py
from base import Base

class Bar(Base):
    def run(self, value):
        print(value)

# main.py
from foo import Foo
from bar import Bar

f1 = Foo()
print(f1)
f1.run(42)
f2 = Foo()
print(f2)
f2.run(34)

b1 = Bar()
print(b1)
b1.run(12)
b2 = Bar()
print(b2)
b2.run(21)
输出:

<foo.Foo object at 0x000001D4D512BE48>
42
<foo.Foo object at 0x000001D4D512BE48>
34
<bar.Bar object at 0x000001D4D512B0B8>
12
<bar.Bar object at 0x000001D4D512BEF0>
21

42
34
12
21
因此,
Foo
是一个单例,而
Bar
不是

奖金问题:


为什么
Singleton(ABC)
不起作用?

ABC只是一个基类。。而不是元类。。您可以从另一个元类派生一个元类,而不仅仅是从另一个类派生。
Base
是从
ABC
派生的。这将提供
Base
元类
ABCMeta
。为什么这对(meta)类
Singleton
不起作用?所以,您似乎将“类Singleton(type):”替换为“类Singleton(ABCMeta):”?“类型”用于什么?这不重要吗?ABC只是一个基类。。而不是元类。。您可以从另一个元类派生一个元类,而不仅仅是从另一个类派生。
Base
是从
ABC
派生的。这将提供
Base
元类
ABCMeta
。为什么这对(meta)类
Singleton
不起作用?所以,您似乎将“类Singleton(type):”替换为“类Singleton(ABCMeta):”?“类型”用于什么?这不重要吗?