这个问题不是讨论单身人士设计模式是否可取,反模式,还是任何宗教战争,而是讨论如何以最蟒蛇的方式在Python中最好地实现这种模式.在这种情况下,我将"最pythonic"定义为表示它遵循"最小惊讶原则".
我有多个类可以成为单例(我的用例是记录器,但这并不重要).当我可以简单地继承或装饰时,我不希望在添加gumph的几个类中混乱.
最好的方法:
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
@singleton
class MyClass(BaseClass):
pass
Run Code Online (Sandbox Code Playgroud)
优点
缺点
m = MyClass(); n = MyClass(); o = type(n)();那时m == n && m != o && n != oclass Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
class MyClass(Singleton, …Run Code Online (Sandbox Code Playgroud) 我需要一个枚举类的双重继承,但也支持我自己的方法。这是上下文:
import abc
from enum import Enum
class MyFirstClass(abc.ABC):
@abc.abstractmethod
def func(self):
pass
class MySecondClass(Enum, MyFirstClass):
VALUE_1 = 0
VALUE_2 = 1
def func(self):
return 42
Run Code Online (Sandbox Code Playgroud)
的声明MySecondClass会产生以下错误:
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Run Code Online (Sandbox Code Playgroud)
我尝试通过执行以下操作来应用此 stackoverflow 解决方案:
class MyMetaClass(type(Enum), type(MyFirstClass)):
pass
class MyFinalClass(Enum, MyFirstClass, metaclass=MyMetaClass):
VALUE_1 = 0
VALUE_2 = 1
def func(self):
return 42
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
TypeError: new enumerations should be created …Run Code Online (Sandbox Code Playgroud) 在本文中, Nick Coghlan讨论了PEP 435 Enum类型的一些设计决策,以及如何EnumMeta进行子类化以提供不同的Enum体验。
但是,我给出的建议(我是stdlib的主要Enum作者)关于使用元类的建议是,在没有充分好的理由的情况下不应该这样做-例如,无法使用类装饰器或专用工具来完成所需的工作隐藏任何丑陋的功能;而在我自己的工作,我已经能够做到我需要什么简单的使用__new__,__init__在创建时,和/或正常类/实例方法Enum类:
然后是一个警告性的故事,在研究Enum,有和没有元类子类化时要小心:
考虑到所有这些,我什么时候需要摆弄EnumMeta自己?
目标是通过从 和 派生的元类创建一个抽象枚举abc.ABCMeta类enum.EnumMeta。例如:
import abc
import enum
class ABCEnumMeta(abc.ABCMeta, enum.EnumMeta):
pass
class A(abc.ABC):
@abc.abstractmethod
def foo(self):
pass
class B(A, enum.IntEnum, metaclass=ABCEnumMeta):
X = 1
class C(A):
pass
Run Code Online (Sandbox Code Playgroud)
现在,在 Python3.7 上,该代码将被正确解释(在 3.6.x 和可能更低的版本上,不会出现错误)。事实上,一切看起来都很棒,我们的 MRO 展示B源自 A和IntEnum。
>>> B.__mro__
(<enum 'B'>, __main__.A, abc.ABC, <enum 'IntEnum'>, int, <enum 'Enum'>, object)
Run Code Online (Sandbox Code Playgroud)
然而,即使B.foo尚未定义,我们仍然可以B毫无问题地实例化并调用foo().
>>> B.X
<B.X: 1>
>>> B(1)
<B.X: 1>
>>> B(1).foo()
Run Code Online (Sandbox Code Playgroud)
这看起来相当奇怪,因为即使我使用自定义元类,从 ABCMeta 派生的任何其他类都无法实例化。
>>> class …Run Code Online (Sandbox Code Playgroud) metaclass ×4
python ×4
enums ×2
base-class ×1
decorator ×1
inheritance ×1
python-3.x ×1
singleton ×1