相关疑难解决方法(0)

在Python中创建单例

这个问题不是讨论单身人士设计模式是否可取,反模式,还是任何宗教战争,而是讨论如何以最蟒蛇的方式在Python中最好地实现这种模式.在这种情况下,我将"最pythonic"定义为表示它遵循"最小惊讶原则".

我有多个类可以成为单例(我的用例是记录器,但这并不重要).当我可以简单地继承或装饰时,我不希望在添加gumph的几个类中混乱.

最好的方法:


方法1:装饰者

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)

优点

  • 装饰器的添加方式通常比多重继承更直观.

缺点

  • 虽然使用MyClass()创建的对象将是真正的单例对象,但MyClass本身是一个函数,而不是一个类,因此您无法从中调用类方法.也是为了m = MyClass(); n = MyClass(); o = type(n)();那时m == n && m != o && n != o

方法2:基类

class 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)

python singleton metaclass decorator base-class

829
推荐指数
14
解决办法
29万
查看次数

涉及 Enum 的多重继承元类冲突

我需要一个枚举类的双重继承,但也支持我自己的方法。这是上下文:

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)

python inheritance enums metaclass

10
推荐指数
1
解决办法
1582
查看次数

什么时候应该继承EnumMeta而不是Enum?

本文中, Nick Coghlan讨论了PEP 435 Enum类型的一些设计决策,以及如何EnumMeta进行子类化以提供不同的Enum体验。

但是,我给出的建议(我是stdlib的主要Enum作者)关于使用元类的建议是,在没有充分好的理由的情况下不应该这样做-例如,无法使用类装饰器或专用工具来完成所需的工作隐藏任何丑陋的功能;而在我自己的工作,我已经能够做到我需要什么简单的使用__new____init__在创建时,和/或正常类/实例方法Enum类:

然后是一个警告性的故事,在研究Enum,有和没有元类子类化时要小心:

考虑到所有这些,我什么时候需要摆弄EnumMeta自己?

python enums metaclass

7
推荐指数
1
解决办法
1960
查看次数

使用 ABCMeta 和 EnumMeta 的抽象枚举类

简单的例子

目标是通过从 和 派生的元类创建一个抽象枚举abc.ABCMetaenum.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源自 AIntEnum

>>> 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)

python metaclass python-3.x

6
推荐指数
1
解决办法
3191
查看次数