Changing `self` for another instance of same object?
I want to create a class, and all objects need to have a unique identifier key
, and If I attempt to create a new instance of the object with a previously existent key, the instance should be the same as the one that already existing.
Similar to a singleton class, but in this case instead of one class, there are many but different.
My first approach was this
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
But when I compare two objects, something like this A = Master('A', 0)
and B = Master('B', 0)
, the B
doesn't share any attributes that It should have, and if the Master class has any _method
(single underscore), It also doesn't appear.
Any Idea how could I do this?
I think this is similar to the Factory Methods Pattern, but I'm still having trouble to find the parallels, or how to implemented in an elegant form.
EDIT:
The class basically has two proprieties and that's it, but many things would Inherit and/or contain instances of this as type, the easy way I thought I could do it, was extracting the properties from the existing instance corresponding to said key
, assigning them to the new instance and abuse from the fact that they will have same hash
output and the the equal
operator will behave according to hashes so I can use ==
and is
operators with no problem.
This Idea solves my problem, but overall I think this could be a common or interesting enough scenario to tackle.
python design-patterns singleton factory-pattern
add a comment |
I want to create a class, and all objects need to have a unique identifier key
, and If I attempt to create a new instance of the object with a previously existent key, the instance should be the same as the one that already existing.
Similar to a singleton class, but in this case instead of one class, there are many but different.
My first approach was this
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
But when I compare two objects, something like this A = Master('A', 0)
and B = Master('B', 0)
, the B
doesn't share any attributes that It should have, and if the Master class has any _method
(single underscore), It also doesn't appear.
Any Idea how could I do this?
I think this is similar to the Factory Methods Pattern, but I'm still having trouble to find the parallels, or how to implemented in an elegant form.
EDIT:
The class basically has two proprieties and that's it, but many things would Inherit and/or contain instances of this as type, the easy way I thought I could do it, was extracting the properties from the existing instance corresponding to said key
, assigning them to the new instance and abuse from the fact that they will have same hash
output and the the equal
operator will behave according to hashes so I can use ==
and is
operators with no problem.
This Idea solves my problem, but overall I think this could be a common or interesting enough scenario to tackle.
python design-patterns singleton factory-pattern
add a comment |
I want to create a class, and all objects need to have a unique identifier key
, and If I attempt to create a new instance of the object with a previously existent key, the instance should be the same as the one that already existing.
Similar to a singleton class, but in this case instead of one class, there are many but different.
My first approach was this
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
But when I compare two objects, something like this A = Master('A', 0)
and B = Master('B', 0)
, the B
doesn't share any attributes that It should have, and if the Master class has any _method
(single underscore), It also doesn't appear.
Any Idea how could I do this?
I think this is similar to the Factory Methods Pattern, but I'm still having trouble to find the parallels, or how to implemented in an elegant form.
EDIT:
The class basically has two proprieties and that's it, but many things would Inherit and/or contain instances of this as type, the easy way I thought I could do it, was extracting the properties from the existing instance corresponding to said key
, assigning them to the new instance and abuse from the fact that they will have same hash
output and the the equal
operator will behave according to hashes so I can use ==
and is
operators with no problem.
This Idea solves my problem, but overall I think this could be a common or interesting enough scenario to tackle.
python design-patterns singleton factory-pattern
I want to create a class, and all objects need to have a unique identifier key
, and If I attempt to create a new instance of the object with a previously existent key, the instance should be the same as the one that already existing.
Similar to a singleton class, but in this case instead of one class, there are many but different.
My first approach was this
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
But when I compare two objects, something like this A = Master('A', 0)
and B = Master('B', 0)
, the B
doesn't share any attributes that It should have, and if the Master class has any _method
(single underscore), It also doesn't appear.
Any Idea how could I do this?
I think this is similar to the Factory Methods Pattern, but I'm still having trouble to find the parallels, or how to implemented in an elegant form.
EDIT:
The class basically has two proprieties and that's it, but many things would Inherit and/or contain instances of this as type, the easy way I thought I could do it, was extracting the properties from the existing instance corresponding to said key
, assigning them to the new instance and abuse from the fact that they will have same hash
output and the the equal
operator will behave according to hashes so I can use ==
and is
operators with no problem.
This Idea solves my problem, but overall I think this could be a common or interesting enough scenario to tackle.
python design-patterns singleton factory-pattern
python design-patterns singleton factory-pattern
edited Nov 15 '18 at 6:33
ekiim
asked Nov 15 '18 at 3:35
ekiimekiim
198210
198210
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Inspired by the answer from A Kruger
, I have another solution building off the use of the __new__
method as suggested. The main difference in this answer is that there is no need to create an inner __Master
class. The __new__
method is automatically called when Master()
is invoked, and is expected to return an instance of the Master
class. In my answer, the __new__
method returns a new instance, if needed, but returns an instance from the existent
dictionary, if possible. Note that the user accesses the Master
class as usual, i.e., they just call Master('A', 0)
. This is made possible by making the Master
class extend object
.
Here is the code:
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))
And here is the output:
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
Note that A
and B
have the same id
(they are the same object). Also note that changes to A
or B
affect each other, since they are the same object.
Agreed -- I realized this as well and made the change to mine just before you posted this. Using the_Master
subclass was derived from examples for singletons
– A Kruger
Nov 15 '18 at 15:56
After a while reading the Python Documentation and doing some tests, turns out the problem is that I didn't knew how__new__
actually works, your solution works perfectly as I need. I still need to resolve my issues with this method. Thanks
– ekiim
Nov 15 '18 at 16:41
add a comment |
I don't think you can do that using the __init__()
method, because a new instance of the class has already been created when that method is called. You probably need to create a factory type method something like:
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
I would really like that the user doesn't bother using the factory method, and that he can instantiate the object as if it where a regular python object, the factory method It's explicit for the programmer but, not that clear the user of the module if you consider they could be not as familiar with this design pattern thingy or OO in genera, the Idea is that the user of the module, is at a basic python level. This works, but doesn't fully solve the issue, check my edit of the question.
– ekiim
Nov 15 '18 at 6:34
add a comment |
You can use the __new__
method to handle this. You don't want to call __init__
unless you want to create a new object with a new key, and __new__
can be used to first check if the key is unique before calling __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
Then you can create the objects with
>>> A = Master('A',0)
>>> B = Master('B',0)
>>> C = Master('A',1)
Since A
and C
have the same key, they will point to the same object and will effectively be the same instance. Since C
has the same key as A
, it updates its value.
>>> print(A.value)
1
Any new changes to A
will be seen in C
, and vice versa.
>>> A.value = 5
>>> print(C.value)
5
But changes to A
and C
will not affect B
, and changes to B
will not affect A
or C
.
Edit:
If you want to copy values but not instances, you could just store the values in the Master.instances
dictionary and check if there's already values for the key.
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
I tried something like this with the new method, but the interface for the object would involve the use ofnew
keyword, and that doesn't feel that pythonic, but It does work, It feels more OO, but I'm not sure, I really want it to be as if you where instantiating a regular python object.
– ekiim
Nov 15 '18 at 6:25
I see, if you just want to copy values, you can just store those values in theMaster.instances
dictionary. Edited answer.
– A Kruger
Nov 15 '18 at 16:18
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53312057%2fchanging-self-for-another-instance-of-same-object%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Inspired by the answer from A Kruger
, I have another solution building off the use of the __new__
method as suggested. The main difference in this answer is that there is no need to create an inner __Master
class. The __new__
method is automatically called when Master()
is invoked, and is expected to return an instance of the Master
class. In my answer, the __new__
method returns a new instance, if needed, but returns an instance from the existent
dictionary, if possible. Note that the user accesses the Master
class as usual, i.e., they just call Master('A', 0)
. This is made possible by making the Master
class extend object
.
Here is the code:
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))
And here is the output:
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
Note that A
and B
have the same id
(they are the same object). Also note that changes to A
or B
affect each other, since they are the same object.
Agreed -- I realized this as well and made the change to mine just before you posted this. Using the_Master
subclass was derived from examples for singletons
– A Kruger
Nov 15 '18 at 15:56
After a while reading the Python Documentation and doing some tests, turns out the problem is that I didn't knew how__new__
actually works, your solution works perfectly as I need. I still need to resolve my issues with this method. Thanks
– ekiim
Nov 15 '18 at 16:41
add a comment |
Inspired by the answer from A Kruger
, I have another solution building off the use of the __new__
method as suggested. The main difference in this answer is that there is no need to create an inner __Master
class. The __new__
method is automatically called when Master()
is invoked, and is expected to return an instance of the Master
class. In my answer, the __new__
method returns a new instance, if needed, but returns an instance from the existent
dictionary, if possible. Note that the user accesses the Master
class as usual, i.e., they just call Master('A', 0)
. This is made possible by making the Master
class extend object
.
Here is the code:
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))
And here is the output:
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
Note that A
and B
have the same id
(they are the same object). Also note that changes to A
or B
affect each other, since they are the same object.
Agreed -- I realized this as well and made the change to mine just before you posted this. Using the_Master
subclass was derived from examples for singletons
– A Kruger
Nov 15 '18 at 15:56
After a while reading the Python Documentation and doing some tests, turns out the problem is that I didn't knew how__new__
actually works, your solution works perfectly as I need. I still need to resolve my issues with this method. Thanks
– ekiim
Nov 15 '18 at 16:41
add a comment |
Inspired by the answer from A Kruger
, I have another solution building off the use of the __new__
method as suggested. The main difference in this answer is that there is no need to create an inner __Master
class. The __new__
method is automatically called when Master()
is invoked, and is expected to return an instance of the Master
class. In my answer, the __new__
method returns a new instance, if needed, but returns an instance from the existent
dictionary, if possible. Note that the user accesses the Master
class as usual, i.e., they just call Master('A', 0)
. This is made possible by making the Master
class extend object
.
Here is the code:
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))
And here is the output:
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
Note that A
and B
have the same id
(they are the same object). Also note that changes to A
or B
affect each other, since they are the same object.
Inspired by the answer from A Kruger
, I have another solution building off the use of the __new__
method as suggested. The main difference in this answer is that there is no need to create an inner __Master
class. The __new__
method is automatically called when Master()
is invoked, and is expected to return an instance of the Master
class. In my answer, the __new__
method returns a new instance, if needed, but returns an instance from the existent
dictionary, if possible. Note that the user accesses the Master
class as usual, i.e., they just call Master('A', 0)
. This is made possible by making the Master
class extend object
.
Here is the code:
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))
And here is the output:
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
Note that A
and B
have the same id
(they are the same object). Also note that changes to A
or B
affect each other, since they are the same object.
answered Nov 15 '18 at 15:37
John AndersonJohn Anderson
3,4961515
3,4961515
Agreed -- I realized this as well and made the change to mine just before you posted this. Using the_Master
subclass was derived from examples for singletons
– A Kruger
Nov 15 '18 at 15:56
After a while reading the Python Documentation and doing some tests, turns out the problem is that I didn't knew how__new__
actually works, your solution works perfectly as I need. I still need to resolve my issues with this method. Thanks
– ekiim
Nov 15 '18 at 16:41
add a comment |
Agreed -- I realized this as well and made the change to mine just before you posted this. Using the_Master
subclass was derived from examples for singletons
– A Kruger
Nov 15 '18 at 15:56
After a while reading the Python Documentation and doing some tests, turns out the problem is that I didn't knew how__new__
actually works, your solution works perfectly as I need. I still need to resolve my issues with this method. Thanks
– ekiim
Nov 15 '18 at 16:41
Agreed -- I realized this as well and made the change to mine just before you posted this. Using the
_Master
subclass was derived from examples for singletons– A Kruger
Nov 15 '18 at 15:56
Agreed -- I realized this as well and made the change to mine just before you posted this. Using the
_Master
subclass was derived from examples for singletons– A Kruger
Nov 15 '18 at 15:56
After a while reading the Python Documentation and doing some tests, turns out the problem is that I didn't knew how
__new__
actually works, your solution works perfectly as I need. I still need to resolve my issues with this method. Thanks– ekiim
Nov 15 '18 at 16:41
After a while reading the Python Documentation and doing some tests, turns out the problem is that I didn't knew how
__new__
actually works, your solution works perfectly as I need. I still need to resolve my issues with this method. Thanks– ekiim
Nov 15 '18 at 16:41
add a comment |
I don't think you can do that using the __init__()
method, because a new instance of the class has already been created when that method is called. You probably need to create a factory type method something like:
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
I would really like that the user doesn't bother using the factory method, and that he can instantiate the object as if it where a regular python object, the factory method It's explicit for the programmer but, not that clear the user of the module if you consider they could be not as familiar with this design pattern thingy or OO in genera, the Idea is that the user of the module, is at a basic python level. This works, but doesn't fully solve the issue, check my edit of the question.
– ekiim
Nov 15 '18 at 6:34
add a comment |
I don't think you can do that using the __init__()
method, because a new instance of the class has already been created when that method is called. You probably need to create a factory type method something like:
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
I would really like that the user doesn't bother using the factory method, and that he can instantiate the object as if it where a regular python object, the factory method It's explicit for the programmer but, not that clear the user of the module if you consider they could be not as familiar with this design pattern thingy or OO in genera, the Idea is that the user of the module, is at a basic python level. This works, but doesn't fully solve the issue, check my edit of the question.
– ekiim
Nov 15 '18 at 6:34
add a comment |
I don't think you can do that using the __init__()
method, because a new instance of the class has already been created when that method is called. You probably need to create a factory type method something like:
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
I don't think you can do that using the __init__()
method, because a new instance of the class has already been created when that method is called. You probably need to create a factory type method something like:
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
answered Nov 15 '18 at 4:31
John AndersonJohn Anderson
3,4961515
3,4961515
I would really like that the user doesn't bother using the factory method, and that he can instantiate the object as if it where a regular python object, the factory method It's explicit for the programmer but, not that clear the user of the module if you consider they could be not as familiar with this design pattern thingy or OO in genera, the Idea is that the user of the module, is at a basic python level. This works, but doesn't fully solve the issue, check my edit of the question.
– ekiim
Nov 15 '18 at 6:34
add a comment |
I would really like that the user doesn't bother using the factory method, and that he can instantiate the object as if it where a regular python object, the factory method It's explicit for the programmer but, not that clear the user of the module if you consider they could be not as familiar with this design pattern thingy or OO in genera, the Idea is that the user of the module, is at a basic python level. This works, but doesn't fully solve the issue, check my edit of the question.
– ekiim
Nov 15 '18 at 6:34
I would really like that the user doesn't bother using the factory method, and that he can instantiate the object as if it where a regular python object, the factory method It's explicit for the programmer but, not that clear the user of the module if you consider they could be not as familiar with this design pattern thingy or OO in genera, the Idea is that the user of the module, is at a basic python level. This works, but doesn't fully solve the issue, check my edit of the question.
– ekiim
Nov 15 '18 at 6:34
I would really like that the user doesn't bother using the factory method, and that he can instantiate the object as if it where a regular python object, the factory method It's explicit for the programmer but, not that clear the user of the module if you consider they could be not as familiar with this design pattern thingy or OO in genera, the Idea is that the user of the module, is at a basic python level. This works, but doesn't fully solve the issue, check my edit of the question.
– ekiim
Nov 15 '18 at 6:34
add a comment |
You can use the __new__
method to handle this. You don't want to call __init__
unless you want to create a new object with a new key, and __new__
can be used to first check if the key is unique before calling __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
Then you can create the objects with
>>> A = Master('A',0)
>>> B = Master('B',0)
>>> C = Master('A',1)
Since A
and C
have the same key, they will point to the same object and will effectively be the same instance. Since C
has the same key as A
, it updates its value.
>>> print(A.value)
1
Any new changes to A
will be seen in C
, and vice versa.
>>> A.value = 5
>>> print(C.value)
5
But changes to A
and C
will not affect B
, and changes to B
will not affect A
or C
.
Edit:
If you want to copy values but not instances, you could just store the values in the Master.instances
dictionary and check if there's already values for the key.
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
I tried something like this with the new method, but the interface for the object would involve the use ofnew
keyword, and that doesn't feel that pythonic, but It does work, It feels more OO, but I'm not sure, I really want it to be as if you where instantiating a regular python object.
– ekiim
Nov 15 '18 at 6:25
I see, if you just want to copy values, you can just store those values in theMaster.instances
dictionary. Edited answer.
– A Kruger
Nov 15 '18 at 16:18
add a comment |
You can use the __new__
method to handle this. You don't want to call __init__
unless you want to create a new object with a new key, and __new__
can be used to first check if the key is unique before calling __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
Then you can create the objects with
>>> A = Master('A',0)
>>> B = Master('B',0)
>>> C = Master('A',1)
Since A
and C
have the same key, they will point to the same object and will effectively be the same instance. Since C
has the same key as A
, it updates its value.
>>> print(A.value)
1
Any new changes to A
will be seen in C
, and vice versa.
>>> A.value = 5
>>> print(C.value)
5
But changes to A
and C
will not affect B
, and changes to B
will not affect A
or C
.
Edit:
If you want to copy values but not instances, you could just store the values in the Master.instances
dictionary and check if there's already values for the key.
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
I tried something like this with the new method, but the interface for the object would involve the use ofnew
keyword, and that doesn't feel that pythonic, but It does work, It feels more OO, but I'm not sure, I really want it to be as if you where instantiating a regular python object.
– ekiim
Nov 15 '18 at 6:25
I see, if you just want to copy values, you can just store those values in theMaster.instances
dictionary. Edited answer.
– A Kruger
Nov 15 '18 at 16:18
add a comment |
You can use the __new__
method to handle this. You don't want to call __init__
unless you want to create a new object with a new key, and __new__
can be used to first check if the key is unique before calling __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
Then you can create the objects with
>>> A = Master('A',0)
>>> B = Master('B',0)
>>> C = Master('A',1)
Since A
and C
have the same key, they will point to the same object and will effectively be the same instance. Since C
has the same key as A
, it updates its value.
>>> print(A.value)
1
Any new changes to A
will be seen in C
, and vice versa.
>>> A.value = 5
>>> print(C.value)
5
But changes to A
and C
will not affect B
, and changes to B
will not affect A
or C
.
Edit:
If you want to copy values but not instances, you could just store the values in the Master.instances
dictionary and check if there's already values for the key.
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
You can use the __new__
method to handle this. You don't want to call __init__
unless you want to create a new object with a new key, and __new__
can be used to first check if the key is unique before calling __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
Then you can create the objects with
>>> A = Master('A',0)
>>> B = Master('B',0)
>>> C = Master('A',1)
Since A
and C
have the same key, they will point to the same object and will effectively be the same instance. Since C
has the same key as A
, it updates its value.
>>> print(A.value)
1
Any new changes to A
will be seen in C
, and vice versa.
>>> A.value = 5
>>> print(C.value)
5
But changes to A
and C
will not affect B
, and changes to B
will not affect A
or C
.
Edit:
If you want to copy values but not instances, you could just store the values in the Master.instances
dictionary and check if there's already values for the key.
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
edited Nov 15 '18 at 16:26
answered Nov 15 '18 at 4:50
A KrugerA Kruger
1,35827
1,35827
I tried something like this with the new method, but the interface for the object would involve the use ofnew
keyword, and that doesn't feel that pythonic, but It does work, It feels more OO, but I'm not sure, I really want it to be as if you where instantiating a regular python object.
– ekiim
Nov 15 '18 at 6:25
I see, if you just want to copy values, you can just store those values in theMaster.instances
dictionary. Edited answer.
– A Kruger
Nov 15 '18 at 16:18
add a comment |
I tried something like this with the new method, but the interface for the object would involve the use ofnew
keyword, and that doesn't feel that pythonic, but It does work, It feels more OO, but I'm not sure, I really want it to be as if you where instantiating a regular python object.
– ekiim
Nov 15 '18 at 6:25
I see, if you just want to copy values, you can just store those values in theMaster.instances
dictionary. Edited answer.
– A Kruger
Nov 15 '18 at 16:18
I tried something like this with the new method, but the interface for the object would involve the use of
new
keyword, and that doesn't feel that pythonic, but It does work, It feels more OO, but I'm not sure, I really want it to be as if you where instantiating a regular python object.– ekiim
Nov 15 '18 at 6:25
I tried something like this with the new method, but the interface for the object would involve the use of
new
keyword, and that doesn't feel that pythonic, but It does work, It feels more OO, but I'm not sure, I really want it to be as if you where instantiating a regular python object.– ekiim
Nov 15 '18 at 6:25
I see, if you just want to copy values, you can just store those values in the
Master.instances
dictionary. Edited answer.– A Kruger
Nov 15 '18 at 16:18
I see, if you just want to copy values, you can just store those values in the
Master.instances
dictionary. Edited answer.– A Kruger
Nov 15 '18 at 16:18
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53312057%2fchanging-self-for-another-instance-of-same-object%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown