Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #20286 > unrolled thread

package extension problem

Started byFabrizio Pollastri <f.pollastri@inrim.it>
First post2012-02-12 19:46 +0100
Last post2012-02-13 09:18 -0800
Articles 8 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  package extension problem Fabrizio Pollastri <f.pollastri@inrim.it> - 2012-02-12 19:46 +0100
    Re: package extension problem Miki Tebeka <miki.tebeka@gmail.com> - 2012-02-13 09:18 -0800
      Re: package extension problem Fabrizio Pollastri <f.pollastri@inrim.it> - 2012-02-13 18:53 +0100
        Re: package extension problem Miki Tebeka <miki.tebeka@gmail.com> - 2012-02-13 09:58 -0800
          Re: package extension problem Terry Reedy <tjreedy@udel.edu> - 2012-02-13 14:12 -0500
        Re: package extension problem Miki Tebeka <miki.tebeka@gmail.com> - 2012-02-13 09:58 -0800
      Re: package extension problem Peter Otten <__peter__@web.de> - 2012-02-13 19:28 +0100
    Re: package extension problem Miki Tebeka <miki.tebeka@gmail.com> - 2012-02-13 09:18 -0800

#20286 — package extension problem

FromFabrizio Pollastri <f.pollastri@inrim.it>
Date2012-02-12 19:46 +0100
Subjectpackage extension problem
Message-ID<mailman.5734.1329072778.27778.python-list@python.org>
Hello,

I wish to extend the functionality of an existing python package by creating
a new package that redefines the relevant classes of the old package. Each
new class inherits the equivalent old class and adds new methods.

In the new package there is something like the following.

import old_package as op

class A(op.A):
     ...
     add new methods
     ...

class B(op.B):
     ...
     add new methods
     ...

Some classes of the old package works as a dictionary of other classes 
of the
same old package. Example: if class A and class B are classes of the old 
package,
B[some_hash] returns an instance of A.

When a program imports the new package and create instances of the new 
class B,
B[some_hash] still returns an instance of the old class A, while I want
an instance of the new class A.

There is a way to solve this problem without redefining in the new 
package all the
methods of the old package that return old classes?


Thanks in advance for any suggestion,
Fabrizio

[toc] | [next] | [standalone]


#20351

FromMiki Tebeka <miki.tebeka@gmail.com>
Date2012-02-13 09:18 -0800
Message-ID<19027093.1215.1329153496662.JavaMail.geo-discussion-forums@ynel5>
In reply to#20286
> B[some_hash] still returns an instance of the old class A, while I want 
an instance of the new class A. 
I don't understand this sentence. How does B[some_hash] related to A?

I've tried the below and it seems to work. Can you paste some code to help us understand more?

-- old.py --
class A:
    pass

-- new.py __
import old
class A(old.A):
    pass

-- main.py --
import new
a = new.A()
a.__class__ # Shows new.A

[toc] | [prev] | [next] | [standalone]


#20353

FromFabrizio Pollastri <f.pollastri@inrim.it>
Date2012-02-13 18:53 +0100
Message-ID<mailman.5765.1329155611.27778.python-list@python.org>
In reply to#20351
Ok. To be more clear, consider the real python package Pandas.

This package defines a Series class and a DataFrame class.
The DataFrame is a matrix that can have columns of
different type.

If I write

import pandas as pd
df = pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})

a data frame with two cols named A and B is created.

If I write

col_A = df['A']

the returned col_A is an instance of Series.

Now , let suppose that I want to extend some functionality of pandas
by adding new methods to both Series and DataFrame classes.

One way to do this is to redefine this classes in a new package
(new_pandas) as follow

import pandas as pd

class Series(pd.Series):
      ...
      add new methods
      ...

class DataFrame(pd.DataFrame):
      ...
      add new methods
      ...

When I use the new package as a pandas substitute and write

import new_pandas as np
df = np.DataFrame({'A':[1,2,3],'B':[4,5,6]})
col_A = df['A']

col_A is an instance of the original pandas and not of the new pandas, 
losing all the added functionality.


Fabrizio











Now, how can I add new methods to extend the functionality of pandas 
classes Series and DataFrame

[toc] | [prev] | [next] | [standalone]


#20354

FromMiki Tebeka <miki.tebeka@gmail.com>
Date2012-02-13 09:58 -0800
Message-ID<19082837.1211.1329155882652.JavaMail.geo-discussion-forums@ynbt34>
In reply to#20353
> import new_pandas as np 
> df = np.DataFrame({'A':[1,2,3],'B':[4,5,6]}) 
> col_A = df['A']
I'm not familiar with pandas, but my *guess* will be that you'll need to override __getitem__ in the new DataFrame.

[toc] | [prev] | [next] | [standalone]


#20359

FromTerry Reedy <tjreedy@udel.edu>
Date2012-02-13 14:12 -0500
Message-ID<mailman.5771.1329160386.27778.python-list@python.org>
In reply to#20354
On 2/13/2012 12:58 PM, Miki Tebeka wrote:
>> import new_pandas as np df =
>> np.DataFrame({'A':[1,2,3],'B':[4,5,6]}) col_A = df['A']
> I'm not familiar with pandas, but my *guess* will be that you'll need
> to override __getitem__ in the new DataFrame.

This is essentially the same problem that if you, for instance, subclass
int as myint, you need to override (wrap) *every* method to get them to 
return myints instead of ints.

class myint(int):
     ...
     def __add__(self, other): return myint(self+other)
     ....

In the OP's case, if the original class is in python, one might be able 
to just change the __class__ attribute. But I would make sure to have a 
good set of tests in any case.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#20355

FromMiki Tebeka <miki.tebeka@gmail.com>
Date2012-02-13 09:58 -0800
Message-ID<mailman.5766.1329155885.27778.python-list@python.org>
In reply to#20353
> import new_pandas as np 
> df = np.DataFrame({'A':[1,2,3],'B':[4,5,6]}) 
> col_A = df['A']
I'm not familiar with pandas, but my *guess* will be that you'll need to override __getitem__ in the new DataFrame.

[toc] | [prev] | [next] | [standalone]


#20357

FromPeter Otten <__peter__@web.de>
Date2012-02-13 19:28 +0100
Message-ID<mailman.5769.1329157703.27778.python-list@python.org>
In reply to#20351
Fabrizio Pollastri wrote:

> Ok. To be more clear, consider the real python package Pandas.
> 
> This package defines a Series class and a DataFrame class.
> The DataFrame is a matrix that can have columns of
> different type.
> 
> If I write
> 
> import pandas as pd
> df = pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})
> 
> a data frame with two cols named A and B is created.
> 
> If I write
> 
> col_A = df['A']
> 
> the returned col_A is an instance of Series.
> 
> Now , let suppose that I want to extend some functionality of pandas
> by adding new methods to both Series and DataFrame classes.
> 
> One way to do this is to redefine this classes in a new package
> (new_pandas) as follow
> 
> import pandas as pd
> 
> class Series(pd.Series):
>       ...
>       add new methods
>       ...
> 
> class DataFrame(pd.DataFrame):
>       ...
>       add new methods
>       ...
> 
> When I use the new package as a pandas substitute and write
> 
> import new_pandas as np
> df = np.DataFrame({'A':[1,2,3],'B':[4,5,6]})
> col_A = df['A']
> 
> col_A is an instance of the original pandas and not of the new pandas,
> losing all the added functionality.

A quick look into the pandas source reveals that the following might work:

# untested
class DataFrame(pd.DataFrame):
    @property
    def _constructor(self):
        return DataFrame # your class
    # your new methods

[toc] | [prev] | [next] | [standalone]


#20352

FromMiki Tebeka <miki.tebeka@gmail.com>
Date2012-02-13 09:18 -0800
Message-ID<mailman.5764.1329153506.27778.python-list@python.org>
In reply to#20286
> B[some_hash] still returns an instance of the old class A, while I want 
an instance of the new class A. 
I don't understand this sentence. How does B[some_hash] related to A?

I've tried the below and it seems to work. Can you paste some code to help us understand more?

-- old.py --
class A:
    pass

-- new.py __
import old
class A(old.A):
    pass

-- main.py --
import new
a = new.A()
a.__class__ # Shows new.A

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web