繁体   English   中英

将“ self”更改为同一对象的另一个实例?

Changing `self` for another instance of same object?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我想创建一个类,并且所有对象都需要具有唯一的标识符key ,并且如果我尝试使用先前存在的键创建该对象的新实例,则该实例应与已存在的实例相同。

与单例类相似,但是在这种情况下,不是一个类,有很多但有所不同。

我的第一个方法是

class Master:
    existent = {}
    def __init__(self, key, value=None):
        try:
            self = Master.existent[key]
            return 
        except KeyError:
            Master.existent[key] = self
        # Rest of the __init__ method

但是当我比较两个对象时,例如A = Master('A', 0)B = Master('B', 0)B不共享它应该具有的任何属性,如果Master类有任何_method (单个下划线),它也不会出现。

知道我该怎么做吗?

我认为这与“工厂方法模式”相似,但是我仍然很难找到相似之处或如何以优雅的形式实现。

编辑:

该类基本上有两个专有属性,仅此而已,但是很多事情都将I​​nherit和/或包含此实例作为类型,我认为我可以做到的简单方法是从与所述key对应的现有实例中提取属性,并为其分配属性从事实,他们将有相同的新实例和滥用hash输出和在equal运营商将根据校验值,这样我可以使用的行为==并且is没有问题的运营商。

这个想法解决了我的问题,但总的来说,我认为这可能是一个常见或有趣的场景,可以解决。

3 个回复

我认为您不能使用__init__()方法来执行此操作,因为调用该方法时已经创建了该类的新实例。 您可能需要创建一个工厂类型的方法,例如:

class Master:
    existent = {}
    init_OK = False

    def __init__(self, key, value=None):
        if not Master.init_OK:
            raise Exception('Direct call to Master() is not allowed')
        Master.init_OK = False
        self.key = key
        self.value = value
        Master.existent[key] = self

    @staticmethod
    def make(key, value=None):
        try:
            inst = Master.existent[key]
        except:
            Master.init_OK = True
            inst = Master(key, value=value)
        return inst

您可以使用__new__方法进行处理。 除非要创建具有新键的新对象,否则不要调用__init__ ,并且可以在调用__init__之前先使用__new__来检查键是否唯一。

class Master(object):

    instances = {}
    def __new__(cls, key, value=None):
        if key in Master.instances:
            return Master.instances[key]
        else:
            instance = super(Master, cls).__new__(cls)
            Master.instances[key] = instance
            return instance

    def __init__(self, key, value=None):
        self.value = value

然后您可以使用创建对象

>>> A = Master('A',0)
>>> B = Master('B',0)
>>> C = Master('A',1)

由于AC具有相同的密钥,因此它们将指向同一对象,并且实际上将是同一实例。 由于CA具有相同的密钥,因此它会更新其值。

>>> print(A.value)
1

A任何新更改都将在C看到,反之亦然。

>>> A.value = 5
>>> print(C.value)
5

但是,改变AC不会影响B ,和改变B不会影响AC

编辑:

如果要复制值而不是实例,则可以将值存储在Master.instances词典中,然后检查键是否已经有值。

class Master(object):

    instances = {}
    def __init__(self, key, value=None):
        if key in Master.instances:
            self.value = Master.instances[key]
        else:
            self.value = value
            Master.instances[key] = value

>>> A = Master('A',0)
>>> C = Master('A',1)
>>> print(C.value)
0

A Kruger回答的启发,我有另一个建议的解决方案,它以__new__方法的使用为__new__ 该答案的主要区别在于无需创建内部__Master类。 调用Master()时会自动调用__new__方法,并且该方法应返回Master类的实例。 在我的回答中, __new__方法返回一个新实例(如果需要),但如果可能的话,从existent字典中返回一个实例。 请注意,用户照常访问Master类,即,他们仅调用Master('A', 0) 通过使Master类扩展object成为可能。

这是代码:

class Master(object):
    existent = {}

    def __init__(self, key, value=None):
        self.key = key
        self.value = value
        if not key in Master.existent:
            Master.existent[key] = self

    def __new__(cls, *args, **kwargs):
        key = args[0]
        if key in Master.existent:
            return Master.existent[key]
        else:
            return super(Master, cls).__new__(cls)

    def __str__(self):
        return('id: ' + str(id(self)) + ', key=' + str(self.key) + ', value=' + str(self.value))

A = Master('A', 0)
print('A = ' + str(A))
B = Master('A', 1)
print('\nAfter B created:')
print('B = ' + str(B))
print('A = ' + str(A))
B.value = 99
print('\nAfter B modified:')
print('B = ' + str(B))
print('A = ' + str(A))
C = Master('C', 3)
print('\nC = ' + str(C))

这是输出:

A = id: 140023450750200, key=A, value=0

After B created:
B = id: 140023450750200, key=A, value=1
A = id: 140023450750200, key=A, value=1

After B modified:
B = id: 140023450750200, key=A, value=99
A = id: 140023450750200, key=A, value=99

C = id: 140023450750256, key=C, value=3

请注意, AB具有相同的id (它们是相同的对象)。 还要注意,对AB更改会相互影响,因为它们是同一对象。

1 从同一对象的不同实例中触发另一个实例的功能

我对Javascript还是一个初学者,正在努力弄清楚如何使用一个实例的函数来触发另一个实例中的函数,反之亦然,这两个类都是同一个类。 让我解释一下我的意思。 我的项目是用Java编写Pomodoro Clock。 Pomodoro是您在指定时间(例如25分钟)工作,然后短暂休息(5分 ...

2 从 ArrayList 中删除对象与同一对象的另一个实例

所以我有一个未定义的对象,我想用另一个具有相同值的未定义对象从数组列表中删除它,这样我就可以有一个类来处理我扔给它的每个对象,而不必创建不同的方法对于每个对象类型。 问题是,即使对象的内容是相同的,因为是另一个实例,整体价值是不同的。 像: Msg.TradeMsg@1d97b82 Msg. ...

3 停止将更改传播到同一对象的多个实例

我是JS中OOP的新手,所以我不知道为什么会这样。 当我更改颜色后,在我的网格上单击以添加其他有色单元格,它将所有其他单元格的颜色更改为我当前的颜色。 如何在每个单元格都可以保持其初始颜色的位置上制作它? 这是单元格对象,以及如何定义颜色。 JSFiddle ...

4 为什么我可以从在同一对象的另一个实例上调用的方法访问一个实例的私有实例变量? [重复]

这个问题已经在这里有了答案: 如何访问该私有变量? 5个答案 在下面的代码中: 当我在实例p1上调用方法“ invoke”并传递p2作为参数时,我能够直接在实例p1上调用的invoke方法内部访问p2的私有实例变量。 为什么这不会引发编译时错误? 即使 ...

6 在forEach的另一个回调中引用同一对象

我正在尝试向对象添加新属性。 似乎在此范围内可以正常工作: 如果我执行console.log(rows),我可以看到foo被添加了正确的值。 如果在forEach中还有另一个回调,则不会再看到更改。 为什么? 是的,回调get被正确触发。 这是getUserById ...

7 如何从另一个类访问同一对象[JAVA]

我正在管理一个GUI,我想知道是否有任何方法可以管理一个类中来自另一个类的GUI。 我会更好地解释:一个类创建GUI对象,是否可以通过其他类来修改相同的GUI距离? 即使我将对象创建为公共对象,也无法访问它而不会收到错误“无法对非静态字段进行静态引用”,因为在Java中没有C-Style全局 ...

8 Java:如何启动同一对象的另一个线程?

我正在尝试模拟某种“服务器”。 我有一个叫做Server的类,它扩展了Thread。 我有一个从1到1,000,000的循环,如果它取决于有多少服务器,则在内部循环,我想每次绕过该循环时都启动一个新线程,以便服务器拾取“请求”来执行它,将服务器标记为繁忙,然后停止此线程,将服务器标记为不繁忙 ...

9 如何从同一对象内的另一个函数调用变量?

我只想知道是否有一种简单的方法可以从同一Object内的另一个函数调用变量? 在此示例中,我希望从schadenfreude function获取var number ,并在irony function for循环中使用该提示号。 谢谢您的帮助。 ...

10 jQuery-引用同一对象的另一个类

这是我的情况: 我有一个涵盖4个不同主题的网站。 我从4个div开始,每个div都有这些主题的标题。 例如, 当我单击“物理” div时,我希望另一个div出现,以详细说明某些物理问题或其他问题。 再次单击将导致“细分div”消失。 我已经在这里与一个“对象”一起工作了: ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2021 STACKOOM.COM