Вопрос

I have some code to do slicing:

class UnlabelledDataset(Dataset):
    ...

    def __getitem__(self,sliceIndex):
        data = self.data[sliceIndex]
        if np.size(data) and not isinstance(sliceIndex, (int,long)):
            return UnlabelledDataset(data) #Create Sliced Object
        else:
            return data

I want to inherit from this class to add functionality. Slicing from the child class, should return a object of the child type with all fields intact.
How do I do this?
If I don't override the __getitem__, (and basically reimplement what is in the parent class, except the line marked #Create Sliced Object).
Then slicing will return a object of type UnlabelledDataset.
If I override it, then I am implementing the same code twice.

I can envision a solution where I use a helper function (possibly with a closure (function) passed in to do the constructing) but I'm hoping there is a more elegant way

EDIT: To clarify, the child classes may have different constructor signatures, to the parent.
Eg the child class might have extra parameters.
For example the child class has a resolution parameter.

Это было полезно?

Решение

In the parent, in place of UnlabelledDataset(data), use self.__class__(data). This should produce the correct answer in both classes.

As a minimalist example:

class A(object):
    def __init__(self, data=None):
        self.data = data

    def f(self, data):
        return self.__class__(data)

class B(A):
    pass

When tested on the ipython command line:

In [15]: a = A()
In [16]: a.f('aaa')
Out[16]: <__main__.A at 0x2e99610>
In [17]: b = B()
In [18]: b.f('bbb')
Out[18]: <__main__.B at 0x2e99790>

Thus, as desired, method f produces a new instance of A when from a and a new instance of B when called from b.

Example with each class having different constructor signatures

If class A and B have different constructors, then we can create a new method, make_new, that handles the difference:

class A(object):
    def __init__(self, data, x):
        self.data = data
        self.x = x

    def make_new(self, myslice):
        return self.__class__(self.data[myslice], self.x)

    def f(self, myslice):
        return self.make_new(myslice)

class B(A):
    def __init__(self, data, x, y):
        self.data = data
        self.x = x
        self.y = y

    def make_new(self, myslice):
        return self.__class__(self.data[myslice], self.x, self.y)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top