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.
def __new__(cls, x):
if isinstance(x, A):
return x
else:
return object.__new__(cls, x)
You can't do this in __init__()
as the object has already been created. Changing self
simply 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()
and dict()
isn't accurate to what you are doing here, as list(some_list)
does not give some_list
, it gives a new list which is a copy of some_list
- the same is true for dict()
:
>>> x = [1, 2, 3]
>>> list(x) is x
False
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)
copy some_a
, and restructure your calling code not to rely on A(some_a) is some_a
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With