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
).