Inheritance but only partly?

P

process

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) ?
 
G

Gary Herron

process said:
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) ?
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
 
M

Matimus

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) ?

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
 
A

Aaron \Castironpi\ Brady

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) ?

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.
 
G

Gary Herron

Gary said:
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

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):
...
 
B

bearophileHUGS

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
 
G

greg

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).
 
M

Michele Simionato

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) ?

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
 
T

Tim Rowe

2008/10/2 process said:
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.
 
S

Simon Brunning

2008/10/3 Tim Rowe said:
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.
(e-mail address removed)
http://www.brunningonline.net/simon/blog/
GTalk: simon.brunning | MSN: small_values | Yahoo: smallvalues |
Twitter: brunns | Facebook: http://tinyurl.com/6f47zo
 
S

Steven D'Aprano

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?
 
G

George Sakkis

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?

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

George
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top