我想创建一个类,并且所有对象都必须具有唯一的标识符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类具有任何{ {1}}(下划线一个),它也不会出现。
任何想法我该怎么做?
我认为这与“工厂方法模式”相似,但是我仍然很难找到相似之处或如何以优雅的形式实现。
编辑:
该类基本上有两个属性,仅此而已,但是很多事情会继承和/或包含该实例作为类型,我认为我可以做到的 easy 方法是从中提取属性。对应于所述_method
的现有实例,将它们分配给新实例并滥用,因为它们将具有相同的key
输出,并且hash
运算符将根据哈希进行操作,因此我可以毫无问题地使用equal
和==
运算符。
这个想法解决了我的问题,但总的来说,我认为这可能是一个常见或有趣的场景,可以解决。
答案 0 :(得分:1)
我认为您无法使用The regular expression pattern C:\Program Files\Microsoft SQL Server\MSSQL14.DEV_MIGRATIONS\MSSQL\DATA\Migration_Data.mdf is not valid.
方法来执行此操作,因为调用该方法时已经创建了该类的新实例。您可能需要创建一个工厂类型的方法,例如:
__init__()
答案 1 :(得分:1)
您可以使用__new__
方法进行处理。除非要创建带有新键的新对象,否则不要调用__init__
,并且可以使用__new__
在调用__init__
之前先检查键是否唯一。
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)
由于A
和C
具有相同的密钥,因此它们将指向相同的对象,并且实际上是相同的实例。由于C
与A
具有相同的密钥,因此它会更新其值。
>>> print(A.value)
1
在A
中将看到对C
的任何新更改,反之亦然。
>>> A.value = 5
>>> print(C.value)
5
但是对A
和C
的更改不会影响B
,对B
的更改不会影响A
或C
。 / p>
编辑:
如果要复制值而不是实例,则可以将值存储在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
答案 2 :(得分:1)
受A Kruger
答案的启发,我有一个建议的解决方案,它基于__new__
方法的使用。该答案的主要区别在于,无需创建内部__Master
类。调用__new__
时会自动调用Master()
方法,并且该方法应返回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
请注意,A
和B
具有相同的id
(它们是相同的对象)。还请注意,A
或B
的更改会相互影响,因为它们是同一对象。