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) ?
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
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
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.
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):
...
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
> 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
>> 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 ;)
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:
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
> 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
> 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
Did you read the next section, "extending generic functions" ?
George