Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Inheritance but only partly?

0 views
Skip to first unread message

process

unread,
Oct 2, 2008, 4:16:40 PM10/2/08
to
Let's say I have a class X which has 10 methods.

I want class Y to inherit 5 of them.

Can I do that? Can I do something along the lines of super(Y, exclude
method 3 4 7 9 10) ?

Gary Herron

unread,
Oct 2, 2008, 4:36:16 PM10/2/08
to pytho...@python.org
> --
> http://mail.python.org/mailman/listinfo/python-list
>
No.

But why do yo care? You can just ignore the 5 you don't want -- their
existence costs you nothing in either memory or execution speed.

You can also redefine the ones you don't want inherited:

class A:
def DontInheritMe(self, ...):
...

Class B(A):
def DontInheritMe(self, ...):
raise NotImplementedError // Or some such


Gary Herron

Matimus

unread,
Oct 2, 2008, 4:44:13 PM10/2/08
to

I think the noral way of doing that is to split the origional class
into two classes.

What you have:

class BaseClass(object):

def method0:
pass

def method1:
pass

def method2:
pass

...

def method9:
pass

What you need:


class BaseClassWant(object):
def method0:
pass

def method1:
pass

...

def method4:
pass

class BaseClassDontWant(object):
def method5:
pass

def method6:
pass

...

def method9:
pass

class BaseClass(BaseClassWant, BaseClassDontWant): # same as BaseClass
above
pass

class YourClass(BaseClassWant):
pass


Matt

Aaron "Castironpi" Brady

unread,
Oct 2, 2008, 4:45:22 PM10/2/08
to

That implies that the 5 you do include don't rely on or call the 5 you
don't. Otherwise you have to inherit them. Then you can refactor
them into:

class X5YouDo: ...
class X5YouDont: ...
class X( X5YouDo, X5YouDont ): ...
class Y( X5YouDo ): ...

If you're looking for restricted visibility, Python does not have it.
It's just handcuffs, and makes things you can't do.

After all, nothing would stop you user from calling:

y= Y()
X5YouDont.DontInheritMe( y, args )

to get at the uninherited methods.

Gary Herron

unread,
Oct 2, 2008, 4:46:56 PM10/2/08
to pytho...@python.org
Gary Herron wrote:
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>>
> No.
>
> But why do yo care? You can just ignore the 5 you don't want -- their
> existence costs you nothing in either memory or execution speed.
>
> You can also redefine the ones you don't want inherited:
>
> class A:
> def DontInheritMe(self, ...):
> ...
>
> Class B(A):
> def DontInheritMe(self, ...):
> raise NotImplementedError // Or some such
>
>
> Gary Herron
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Here's another (very Python) possibility

class Base:
class m1(self, ...):
...
class m2(self, ...):
...

class NotInheritable:
class m3(self, ...):
...

class A(Base, NotInheritable);
...

class B(Base):
...

bearoph...@lycos.com

unread,
Oct 2, 2008, 6:11:12 PM10/2/08
to
Gary Herron:

> You can also redefine the ones you don't want inherited:
> class A:
> def DontInheritMe(self, ...):
> ...
> Class B(A):
> def DontInheritMe(self, ...):
> raise NotImplementedError // Or some such

I have never used something like this, but the OP may use a masking
class too:

class A(object):
def m1(self): pass
def m2(self): pass
def m3(self): pass
def m4(self): pass

class Mask(object):
def m3(self): raise NotImplementedError
def m4(self): raise NotImplementedError

class B(Mask, A):
pass

a = A()
a.m1()
a.m2()
a.m3()
a.m4()

b = B()
b.m1()
b.m2()
b.m3() # raises
b.m4() # raises

In a language without multiple inheritance you need a different trick,
I presume.
What's the name of this python design pattern? :-)

Bye,
bearophile

greg

unread,
Oct 3, 2008, 5:28:40 AM10/3/08
to
bearoph...@lycos.com wrote:

> class Mask(object):
> def m3(self): raise NotImplementedError
> def m4(self): raise NotImplementedError

> What's the name of this python design pattern? :-)

Don't know. Perhaps we could call it the FigLeaf pattern
(covering up what you don't want seen)?

There's another possibility that's even more pythonish
(I won't say pythonic, since it's not necessarily
a *recommended* thing to do):

class A:
m1 = B.__dict__['m1']
m2 = B.__dict__['m2']
...

I propose calling this the Magpie pattern (stealing
the shiny baubles you want and hiding them away in
your own nest).

--
Greg

Peter Otten

unread,
Oct 3, 2008, 5:51:59 AM10/3/08
to
greg wrote:

>> class Mask(object):
>> def m3(self): raise NotImplementedError
>> def m4(self): raise NotImplementedError
>
>> What's the name of this python design pattern? :-)
>
> Don't know. Perhaps we could call it the FigLeaf pattern
> (covering up what you don't want seen)?

Braghettone ;)

Michele Simionato

unread,
Oct 3, 2008, 6:32:52 AM10/3/08
to

Don't use inheritance, use delegation or just copy the methods you
need:

class A(object):
def meth_a(self):
pass

class B(object):
meth_a = A.meth_a.im_func


IMO, if you have methods that you want to use in different classes,
this is hint that
you are in need of generic functions. See this blog post for an
example:

http://www.artima.com/weblogs/viewpost.jsp?thread=237764

Tim Rowe

unread,
Oct 3, 2008, 7:27:50 AM10/3/08
to pytho...@python.org
2008/10/2 process <circul...@gmail.com>:

> Let's say I have a class X which has 10 methods.
>
> I want class Y to inherit 5 of them.
>
> Can I do that?

As others have said, no. What nobody seems to have said yet is why. If
Y descends from X, you are saying that Y is an X; that a Y can be used
anywhere an X can. If Y doesn't support some methods of X then it is
*not* an X, and *can't* be used anywhere an X can.

Rather than looking at workarounds, as others have, I think you need
to go back to your design and work out what's gone wrong that you
/want/ to descend Y from X. Your present design is wrong, plain and
simple. Working around it won't fix that.

--
Tim Rowe

Simon Brunning

unread,
Oct 3, 2008, 9:29:49 AM10/3/08
to Python List
2008/10/3 Tim Rowe <dig...@gmail.com>:

> As others have said, no. What nobody seems to have said yet is why. If
> Y descends from X, you are saying that Y is an X; that a Y can be used
> anywhere an X can. If Y doesn't support some methods of X then it is
> *not* an X, and *can't* be used anywhere an X can.

See <http://en.wikipedia.org/wiki/Liskov_substitution_principle>.

--
Cheers,
Simon B.
si...@brunningonline.net
http://www.brunningonline.net/simon/blog/
GTalk: simon.brunning | MSN: small_values | Yahoo: smallvalues |
Twitter: brunns | Facebook: http://tinyurl.com/6f47zo

Steven D'Aprano

unread,
Oct 3, 2008, 11:56:52 PM10/3/08
to
On Fri, 03 Oct 2008 03:32:52 -0700, Michele Simionato wrote:

> IMO, if you have methods that you want to use in different classes, this
> is hint that
> you are in need of generic functions. See this blog post for an example:
>
> http://www.artima.com/weblogs/viewpost.jsp?thread=237764


That's a very interesting article, but I'm afraid I don't understand what
makes them "generic functions" as opposed to just functions. Your simple
generic example:


from pkgutil import simplegeneric

@simplegeneric
def print_out(self, text, *args):
if args:
text = text % args
print >> self.stdout, text
# and similar for print_err and readln_in

class FileOut(object):
def __init__(self):
self.stdout = file('out.txt', 'w')

print_out(FileOut(), 'writing on file') # prints a line on out.txt

doesn't seem to do anything extra that the following would do:


def print_out2(obj, text, *args):
if args:
text = text % args
print >> obj.stdout, text

class FileOut2(object):
def __init__(self):
self.stdout = file('out2.txt', 'w')

print_out(FileOut2(), 'writing on file')

What's the difference?


--
Steven

George Sakkis

unread,
Oct 5, 2008, 5:01:29 PM10/5/08
to
On Oct 3, 11:56 pm, Steven D'Aprano <st...@REMOVE-THIS-

Did you read the next section, "extending generic functions" ?

George

0 new messages