只有在不存在时才创建新实例 else return 存在而没有新的初始化
Create new instance only if not exist else return existing without new initialization
我想自己存储 class 中的实例。如果 __new__
方法正在调用它应该 return 实例如果存在,但没有新的初始化。
我写了一个最小的例子:
from pprint import pprint
class A:
_l = {}
def __init__(self, name : str, initalize: bool = True, **kwargs) -> None:
print("In init")
if kwargs.get('initalize'):
print("no initialization")
print(self.numbers)
self.name = self.name
self.numbers = self.numbers
return
self.name = name
self.numbers = []
def __new__(cls, name:str, *args, **kwargs):
a = A._l.get(name)
if a:
print("Use existing A")
kwargs['initalize'] = False
return a
print(f"Create new A object with name: {name}")
cls._l[name] = super(A, cls).__new__(cls)
return cls._l[name]
l = [
A('Alex'), A('Gerrit'), A('Jannis'), A('Hannes'),
A('Hannes'), A('Alex'), A('Mumpitz')
]
print("\n#### 1 ####")
c = 0
for a in l:
a.numbers.append(1)
a.numbers.append(2)
print(f"[{c}] {a} : {a.numbers}")
c += 1
print("\n#### 2 ####")
for n in ['Alex', 'Mumpitz']:
current = A(n)
pprint(f"current: {current}")
current.numbers.append(3)
print("\n#### 3 ####")
for a in l:
print(a.numbers)
输出如下所示:
Create new A object with name: Alex
In init
Create new A object with name: Gerrit
In init
Create new A object with name: Jannis
In init
Create new A object with name: Hannes
In init
Use existing A
In init
Use existing A
In init
Create new A object with name: Mumpitz
In init
#### 1 ####
[0] <__main__.A object at 0x7f7b2af87d30> : [1, 2]
[1] <__main__.A object at 0x7f7b2af87cd0> : [1, 2]
[2] <__main__.A object at 0x7f7b2af87be0> : [1, 2]
[3] <__main__.A object at 0x7f7b2af874c0> : [1, 2]
[4] <__main__.A object at 0x7f7b2af874c0> : [1, 2, 1, 2]
[5] <__main__.A object at 0x7f7b2af87d30> : [1, 2, 1, 2]
[6] <__main__.A object at 0x7f7b2af87460> : [1, 2]
#### 2 ####
Use existing A
In init
'current: <__main__.A object at 0x7f7b2af87d30>'
Use existing A
In init
'current: <__main__.A object at 0x7f7b2af87460>'
#### 3 ####
[3]
[1, 2]
[1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2]
[3]
[3]
我想要什么?第三个输出应该类似于以下代码,但没有创建外部 class 或 holder.
#### 3 ####
[1, 2, 3]
[1, 2]
[1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2]
[1, 2, 3]
[1, 2, 3]
首先,我尝试以最少的更改完成您的代码。我添加了 hasattr
作为初始化是否发生的测试,而不是不工作的 initialize
标志:
class A:
_l = {}
def __init__(self, name : str, **kwargs) -> None:
print("In init")
if hasattr(self, 'name'):
print("no initialization")
return
self.name = name
self.numbers = []
def __new__(cls, name:str, *args, **kwargs):
a = A._l.get(name)
if a:
print("Use existing A")
return a
print(f"Create new A object with name: {name}")
cls._l[name] = super(A, cls).__new__(cls)
return cls._l[name]
我正在添加一个我觉得更简单的带有工厂函数的替代方案:
class _A:
def __init__(self, name : str) -> None:
print(f"In init A({name})")
self.name = name
self.numbers = []
def A(name, _instances={}): # deliberate use of a mutable default arg
if name not in _instances:
_instances[name] = _A(name)
return _instances[name]
首先,我正在考虑另一种选择,其中 dict
子类添加了 __missing__
函数,但所有 A(name)
都必须替换为 A[name]
,所以我放弃了这个想法。
然而,输出并不完全符合预期:
#### 3 ####
[1, 2, 1, 2, 3]
[1, 2]
[1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2, 3]
[1, 2, 3]
但我希望它是正确的。
我想自己存储 class 中的实例。如果 __new__
方法正在调用它应该 return 实例如果存在,但没有新的初始化。
我写了一个最小的例子:
from pprint import pprint
class A:
_l = {}
def __init__(self, name : str, initalize: bool = True, **kwargs) -> None:
print("In init")
if kwargs.get('initalize'):
print("no initialization")
print(self.numbers)
self.name = self.name
self.numbers = self.numbers
return
self.name = name
self.numbers = []
def __new__(cls, name:str, *args, **kwargs):
a = A._l.get(name)
if a:
print("Use existing A")
kwargs['initalize'] = False
return a
print(f"Create new A object with name: {name}")
cls._l[name] = super(A, cls).__new__(cls)
return cls._l[name]
l = [
A('Alex'), A('Gerrit'), A('Jannis'), A('Hannes'),
A('Hannes'), A('Alex'), A('Mumpitz')
]
print("\n#### 1 ####")
c = 0
for a in l:
a.numbers.append(1)
a.numbers.append(2)
print(f"[{c}] {a} : {a.numbers}")
c += 1
print("\n#### 2 ####")
for n in ['Alex', 'Mumpitz']:
current = A(n)
pprint(f"current: {current}")
current.numbers.append(3)
print("\n#### 3 ####")
for a in l:
print(a.numbers)
输出如下所示:
Create new A object with name: Alex
In init
Create new A object with name: Gerrit
In init
Create new A object with name: Jannis
In init
Create new A object with name: Hannes
In init
Use existing A
In init
Use existing A
In init
Create new A object with name: Mumpitz
In init
#### 1 ####
[0] <__main__.A object at 0x7f7b2af87d30> : [1, 2]
[1] <__main__.A object at 0x7f7b2af87cd0> : [1, 2]
[2] <__main__.A object at 0x7f7b2af87be0> : [1, 2]
[3] <__main__.A object at 0x7f7b2af874c0> : [1, 2]
[4] <__main__.A object at 0x7f7b2af874c0> : [1, 2, 1, 2]
[5] <__main__.A object at 0x7f7b2af87d30> : [1, 2, 1, 2]
[6] <__main__.A object at 0x7f7b2af87460> : [1, 2]
#### 2 ####
Use existing A
In init
'current: <__main__.A object at 0x7f7b2af87d30>'
Use existing A
In init
'current: <__main__.A object at 0x7f7b2af87460>'
#### 3 ####
[3]
[1, 2]
[1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2]
[3]
[3]
我想要什么?第三个输出应该类似于以下代码,但没有创建外部 class 或 holder.
#### 3 ####
[1, 2, 3]
[1, 2]
[1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2]
[1, 2, 3]
[1, 2, 3]
首先,我尝试以最少的更改完成您的代码。我添加了 hasattr
作为初始化是否发生的测试,而不是不工作的 initialize
标志:
class A:
_l = {}
def __init__(self, name : str, **kwargs) -> None:
print("In init")
if hasattr(self, 'name'):
print("no initialization")
return
self.name = name
self.numbers = []
def __new__(cls, name:str, *args, **kwargs):
a = A._l.get(name)
if a:
print("Use existing A")
return a
print(f"Create new A object with name: {name}")
cls._l[name] = super(A, cls).__new__(cls)
return cls._l[name]
我正在添加一个我觉得更简单的带有工厂函数的替代方案:
class _A:
def __init__(self, name : str) -> None:
print(f"In init A({name})")
self.name = name
self.numbers = []
def A(name, _instances={}): # deliberate use of a mutable default arg
if name not in _instances:
_instances[name] = _A(name)
return _instances[name]
首先,我正在考虑另一种选择,其中 dict
子类添加了 __missing__
函数,但所有 A(name)
都必须替换为 A[name]
,所以我放弃了这个想法。
然而,输出并不完全符合预期:
#### 3 ####
[1, 2, 1, 2, 3]
[1, 2]
[1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2]
[1, 2, 1, 2, 3]
[1, 2, 3]
但我希望它是正确的。