On Fri, 18 Jun 2010 16:30:00 +0200, Christoph Groth wrote: > If other is of type Base already, just "pass it on". Otherwise, > construct an instance of Base from it. > > **************************************************************** import > numpy as np > > class Base: > def __init__(self, other): > if isinstance(other, type(self)): > self = other > return
This does not do what you think it does. I wonder whether you've actually tried it? >>> import numpy as np >>> a = np.identity(4) >>> b = Base(a) # works >>> c = Base(b) # doesn't work >>> b.a array([[ 1., 0.], [ 0., 1.]]) >>> c.a Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: Base instance has no attribute 'a' In your __init__ method, the line: self = other does NOT do what you think. All it does is re-bind the name "self" to refer to the other object, while leaving the instance untouched. Consequently, the rest of the initialisation code never gets executed and your instance is uninitialised. To do what you are trying to do, you need to do two things: (1) Use a new-style class, not a classic (old-style) class; and (2) Use the constructor __new__ and not the initialiser __init__. And then you should change your mind and not do it, because you will be opening a huge can of horrible bugs that will be really hard to debug. The reason being, your class is *mutable*, and you will find yourself having code where you think you have two different instances but you actually only have one instance with two different names. Here's a simple example demonstrating why this is a bad idea: >>> class Recycler(object): ... def __new__(cls, other): ... if isinstance(other, cls): ... return other ... else: ... instance = super(Recycler, cls).__new__(cls, other) ... return instance ... def __init__(self, other): ... # Don't re-initialise when self has been recycled. ... if self is other: ... return ... self.attr = other ... >>> a = Recycler(42) >>> a.attr 42 >>> b = Recycler(a) >>> b.attr 42 >>> b.attr = 23 >>> a.attr 23 a and b are the same object, and whatever you do to one, you do to the other. Object constructors should construct new instances, not give you back an existing instance which is already in use elsewhere. However, if you make the class *immutable*, then it is perfectly safe, because you can't modify immutable objects and therefore it doesn't matter whether a and b refer to two different instances or the same instance. For example, Python caches small integers and reuses them, as a memory optimization: >>> a = int("42") >>> b = int("42") >>> a is b True but doesn't bother for larger integers to avoid filling the cache will billions of ints that will never be re-used: >>> a = int("4200207") >>> b = int("4200207") >>> a is b False This is safe, since you can't change the value of the object 42. (You can rebind the name "a", but not modify the object itself.) So, to recap: * you aren't doing what you think you're doing; * even if you were, you shouldn't; * unless you make the class immutable. -- Steven -- http://mail.python.org/mailman/listinfo/python-list