Python class 在每次调用时继承单例初始化实例
Python class inherited singleton inits instance on every call
我正在尝试实现 class 所描述的继承单例 here (Method 2). Going over the question and the extensive chosen answer 我试图实现以下内容:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not isinstance(cls._instance, cls):
cls._instance = object.__new__(cls, *args, **kwargs)
cls._instance._initialized = False
return cls._instance
class A(Singleton):
def __init__(self):
print "Init is called"
class B(Singleton):
def __init__(self):
print "Init is called"
您可能猜到了,每当我创建 Class A
时,我都会得到相同的对象,但会调用 __init__
。这是有问题的,因为 Class A
可能因此更改其所有成员。
正在做:
a1 = A()
a2 = A()
print a1 == a2
将导致:
>> Init is called
>> Init is called
>> True
This question poses a similar issue but I would prefer not to use the solution there as it doesn't include the inheritance and I have at least 2 classes that needs the Singleton
inheritance. I tried to implement the solution here but it didn't work. The solution here 有效,但它涉及更改 Class A
和 Class B
,我不想这样做。
有没有办法更改 Singleton
实现,这样 __init__
就不会在每次创建时都被调用? (我不能使用 metaclasses,因为 A
和 B
都继承了其他 classes,例如抽象 classes 和它们自己的 metaclasses).
谢谢
在现代 Python 中,这可以通过编写一个 __init_subclass__
方法来完成,该方法可以装饰 __init__
使其在 运行 之前检查 cls._instance
。
照原样,(即你也需要 Python 2) - 我认为更简单的事情是 __new__
用 NOP 方法修补 __init__
如果实例已存在:
_nop_init = lambda self, *args, **kw: None
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not isinstance(cls._instance, cls):
cls._instance = object.__new__(cls, *args, **kwargs)
cls._instance._initialized = False
# Python 2 have to check in the cls.__dict__ - Py3 could check the attribute directly:
elif cls.__dict__.get("__init__", None) is not _nop_init:
cls.__init__ = _nop_init
return cls._instance
class A(Singleton):
def __init__(self):
print "Init is called"
class B(Singleton):
def __init__(self):
print "Init is called"
额外信息调用__init__
的语言机制内置于type
的__call__
方法中-元class 对于 Python 中的所有 classes。它会在实例化时调用目标 class 的 __new__
和 __init__
方法,因此,使用 metaclass,很容易从自定义对象控制这些调用元class。有趣的是,当 __new__
不 return 时,目标 class 的实例不会被调用。 (在这个单例中,单例 是 te class 的一个实例,因此它被称为。
真实世界示例:上次我编写单例代码时,我选择避免在其自己的代码中重新运行 __init__
- 正弦它是项目中唯一的单例,在 __new__
中不需要通用代码:
https://github.com/jsbueno/pythonchain/blob/1f9208dc8bd2741a574adc1bf745d218e4314e4a/pythonchain/block.py#L276
我正在尝试实现 class 所描述的继承单例 here (Method 2). Going over the question and the extensive chosen answer 我试图实现以下内容:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not isinstance(cls._instance, cls):
cls._instance = object.__new__(cls, *args, **kwargs)
cls._instance._initialized = False
return cls._instance
class A(Singleton):
def __init__(self):
print "Init is called"
class B(Singleton):
def __init__(self):
print "Init is called"
您可能猜到了,每当我创建 Class A
时,我都会得到相同的对象,但会调用 __init__
。这是有问题的,因为 Class A
可能因此更改其所有成员。
正在做:
a1 = A()
a2 = A()
print a1 == a2
将导致:
>> Init is called
>> Init is called
>> True
This question poses a similar issue but I would prefer not to use the solution there as it doesn't include the inheritance and I have at least 2 classes that needs the Singleton
inheritance. I tried to implement the solution here but it didn't work. The solution here 有效,但它涉及更改 Class A
和 Class B
,我不想这样做。
有没有办法更改 Singleton
实现,这样 __init__
就不会在每次创建时都被调用? (我不能使用 metaclasses,因为 A
和 B
都继承了其他 classes,例如抽象 classes 和它们自己的 metaclasses).
谢谢
在现代 Python 中,这可以通过编写一个 __init_subclass__
方法来完成,该方法可以装饰 __init__
使其在 运行 之前检查 cls._instance
。
照原样,(即你也需要 Python 2) - 我认为更简单的事情是 __new__
用 NOP 方法修补 __init__
如果实例已存在:
_nop_init = lambda self, *args, **kw: None
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not isinstance(cls._instance, cls):
cls._instance = object.__new__(cls, *args, **kwargs)
cls._instance._initialized = False
# Python 2 have to check in the cls.__dict__ - Py3 could check the attribute directly:
elif cls.__dict__.get("__init__", None) is not _nop_init:
cls.__init__ = _nop_init
return cls._instance
class A(Singleton):
def __init__(self):
print "Init is called"
class B(Singleton):
def __init__(self):
print "Init is called"
额外信息调用__init__
的语言机制内置于type
的__call__
方法中-元class 对于 Python 中的所有 classes。它会在实例化时调用目标 class 的 __new__
和 __init__
方法,因此,使用 metaclass,很容易从自定义对象控制这些调用元class。有趣的是,当 __new__
不 return 时,目标 class 的实例不会被调用。 (在这个单例中,单例 是 te class 的一个实例,因此它被称为。
真实世界示例:上次我编写单例代码时,我选择避免在其自己的代码中重新运行 __init__
- 正弦它是项目中唯一的单例,在 __new__
中不需要通用代码:
https://github.com/jsbueno/pythonchain/blob/1f9208dc8bd2741a574adc1bf745d218e4314e4a/pythonchain/block.py#L276