仅当不存在时才创建新实例,否则返回现有而不进行新的初始化

如何解决仅当不存在时才创建新实例,否则返回现有而不进行新的初始化

我想在类本身中存储实例。并且如果 __new__ 方法正在调用它应该返回实例(如果存在),但没有新的初始化。

我写了一个最小的例子:

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('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]
[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]
[3]
[3]

我想要什么?第三个输出应类似于以下代码,但不创建外部类或持有者。

#### 3 ####
[1,3] 
[1,3]
[1,3]

解决方法

首先,我尝试以最少的更改完成您的代码。我没有添加不工作的 initialize 标志,而是添加了 hasattr 作为初始化是否发生的测试:

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,3]
[1,2]
[1,3]

但我希望它是正确的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?