I need to create a class that mimics this behavior (in mathematics, we say list, dict, are “idempotent”):
>>> list(list([3,4]))
[3, 4]
>>> dict({'a':1,'b':2})
{'a':1,'b':2}
So, if A is my class, I want to write
>>> a = A(1)
>>> b = A(a)
>>> b == a
True
I imagine my class A has to look like this :
class A(object):
def __init__(self,x):
if isinstance(x, A) :
self = x
else :
self.x = x
self.y = 'hello'
I try it
>>> A(1).x
1
>>> A(A(1)).x
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'A' object has no attribute 'x'
It does not work !
I don’t want to copy x attributes in self, i just want self to BE x or “point” x
Some idea ?
Thanks
What you are looking for is the
__new__()method, which takes is run before the class is constructed, as opposed to__init__(), which takes place after. With__new__()you can hook in and replace the object being created.You can’t do this in
__init__()as the object has already been created. Changingselfsimply changes the value of the local variable, it doesn’t affect the object.It’s also worth noting that type-checking is almost always the wrong thing to do in Python. Instead, check to see if the class has the information/attributes you need. This way, someone can create a class that acts like yours and works with your code.
As a final word of warning, this is pretty confusing behaviour – people won’t expect your class to act like this and it’s generally not a great idea. Your example of
list()anddict()isn’t accurate to what you are doing here, aslist(some_list)does not givesome_list, it gives a new list which is a copy ofsome_list– the same is true fordict():When you call a constructor, it’s natural to expect a new object, rather than a reference to the existing one. I would recommend making
A(some_a)copysome_a, and restructure your calling code not to rely onA(some_a) is some_a).