constructing an object from another instance of the same class

Christoph Groth cwg at falma.de
Fri Jun 18 10:30:00 EDT 2010


Bruno Desthuilliers <bruno.42.desthuilliers at websiteburo.invalid> writes:

>> It seems to me that in this way I might get problems when I pass an
>> instance of Derived_from_my_type to bar, as it will become an
>> instance of My_type.
>
> The instance you pass to bar won't "become" anything else. You create
> a new My_type instance from the Derived_from_my_type one's values, and
> rebinding the _local_ name 'arg' only affects the local namespace.

I understand that it won't become an instance of My_type globally.  But
it will become locally and this breaks polymorphism.  (See code example
I provide at the end)

>>  In C++
>
> Forget about C++ - Python is a different beast !-)

Still, it is useful and interesting to compare languages.  Like in the
real world it is also insightful to compare the grammar of quite
different languages.

>> (which I know better than python) I would make bar accept a const
>> reference to My_type.  Then I could use it directly with instances of
>> My_type, Derived_from_my_type and other types which can be converted
>> into My_type.
>
> If you only worry about being able to use any "My_type like" object -
> that is, any object implementing a given subset of My_type's
> interface, then just document your expectations in the function's
> docstring and use whatever object is passed in as if it was a My_type
> instance. Period. As long as you document what your function expects,
> it's the caller's responsaibility to make sure it provides something
> compatible. If he don't, well he'll get a nice traceback.

This is not what I am worrying about.  I will try to be more explicit.

I would like to have a class for a "special matrix".  This is an
ordinary 2n by 2n matrix which can be thought of as consisting of four n
by n sized blocks.

At this moment, I just use normal numpy arrays (or anything which
behaves like them).  But I have very good reasons to actually have a
class for these special matrices.  Still, I would like to be able to
call functions which work with "special matrices" with plain numpy
arrays as arguments.  In that case, the arguments which are plain
matrices should be converted to "special" ones such that the main part
of the function can assume to always work with "special matrices".

The code attached in the end (which is a complete runnable script)
should illustrate what I mean.

This example works as I want except that when bar is called with a an
argument of type Derived, it behaves as Base.  Also, I am not sure
whether there is a nicer way to achieve the following functionality for
Base.__init__:

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
        n = other.shape[0]
        assert n == other.shape[1]
        assert n % 2 == 0
        n //= 2
        self.a = other[0 : n, 0 : n]
        self.b = other[n : 2*n, 0 : n]
        self.c = other[0 : n, n : 2*n]
        self.d = other[n : 2*n, n : 2*n]

    def hello(self):
        print 'hello from Base'

class Derived(Base):
    def hello(self):
        print 'hello from Derived'

def bar(arg):
    arg = Base(arg)
    # Do something useful with arg.{a..d}
    arg.hello()

# This works.
a = np.identity(4)
bar(a)

# And this also.
a = Base(np.identity(4))
bar(a)

# But this prints "hello from Base"!
a = Derived(np.identity(4))
bar(a)




More information about the Python-list mailing list