I am not at all sure I understand what you want, but something like this may be it. You can't have an __init__
with this technique, because if you do, it will be called regardless of whether __new__
returned a new object.
class A(object):
def __new__(cls, obj):
if isinstance(obj, cls):
return obj
rv = object.__new__(cls)
# everything you would normally put in __init__
# goes here instead
rv._obj = obj
return rv
# for instance:
def __repr__(self):
return "A({})".format(repr(self._obj))
>>> A()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __new__() takes exactly 2 arguments (1 given)
>>> A(1)
A(1)
>>> A(A(1))
A(1)
Not being able to use __init__
is troublesome, particularly if you need to subclass A
. Here's a way to work around that:
class A(object):
def __new__(cls, obj):
if isinstance(obj, cls):
return obj
rv = object.__new__(cls)
rv._initialized = False
return rv
def __init__(self, obj):
if self._initialized: return
self._obj = obj
self._initialized = True
class B(A):
def __init__(self, obj):
if self._initialized: return
A.__init__(self, obj)
self._otherthing = "foo"
You have to check self._initialized
in every subclass's __init__
method, unfortunately.