Re: callable virtual method

Discussion in 'Python' started by Jean-Michel Pichavant, Aug 14, 2009.

  1. MRAB wrote:
    > Jean-Michel Pichavant wrote:
    >> Hi fellows,
    >>
    >> Does anyone know a way to write virtual methods (in one virtual
    >> class) that will raise an exception only if called without being
    >> overridden ?
    >> Currently in the virtual method I'm checking that the class of the
    >> instance calling the method has defined that method as well.
    >>
    >> Example:
    >>
    >> class Stream(object):
    >> """Interface of all stream objects"""
    >> def resetStats(self):
    >> """Reset the stream statistics. All values a zeroed except the
    >> date."""
    >> _log.info('Reset statistics of %s' % self)
    >> if self.__class__.resetStats == Stream.resetStats:
    >> raise NotImplementedError()
    >>
    >> It works but it's tedious, I have to add these 2 lines to every
    >> virtual method, changing the content of the 2 lines.
    >>
    >> Maybe there is a nice/builtin way to do so (python 2.4)
    >>

    > Why are you checking which class it's in? The method in the base class
    > will be called only if it hasn't been overridden in the subclass.


    Sorry guys (means guys *and* gals :eek:p ), I realized I've not been able
    to describe precisely what I want to do.
    I'd like the base class to be virtual (aka abstract). However it may be
    abstract but it does not mean it cannot do some usefull stuff.


    Here is the schema of my abstract methods :

    class Interface(object):
    def method(self):
    # ---------------------
    # some common stuff executed here
    # ---------------------
    print 'hello world'
    # ---------------------
    # here shall stand child specific stuff (empty in the interface
    method)
    # ---------------------
    if self.__class__.method == Interface.method:
    raise NotImplementedError('You should have read the f******
    manual ! You must override this method.')

    class GoodChild(Interface):
    def method(self):
    Interface.method(self) # I want to process the cool stuff done my
    the base Interface
    # ------------------------
    # Specific GoodChild stuff here
    # ------------------------
    print 'I am a good'
    return 'perfect'

    class BadChild(Interface):
    pass #I'm too lazy


    good = GoodChild()
    bad = BadChild()

    good.method()
    ....hello world
    ....I am a good

    bad.method()
    ....NotImplementedError: You should have read the f****** manual ! You
    must override this method.


    The reason I'd like to do so: I'll be providing the Interface, but child
    classes will be overridden by others. Having a reliable error RTFM
    feedback is a time saver, for me and the users.
    I hope I clarified my issue.

    JM
    Jean-Michel Pichavant, Aug 14, 2009
    #1
    1. Advertising

  2. Jean-Michel Pichavant schrieb:
    > MRAB wrote:
    >> Jean-Michel Pichavant wrote:
    >>> Hi fellows,
    >>>
    >>> Does anyone know a way to write virtual methods (in one virtual
    >>> class) that will raise an exception only if called without being
    >>> overridden ?
    >>> Currently in the virtual method I'm checking that the class of the
    >>> instance calling the method has defined that method as well.
    >>>
    >>> Example:
    >>>
    >>> class Stream(object):
    >>> """Interface of all stream objects"""
    >>> def resetStats(self):
    >>> """Reset the stream statistics. All values a zeroed except the
    >>> date."""
    >>> _log.info('Reset statistics of %s' % self)
    >>> if self.__class__.resetStats == Stream.resetStats:
    >>> raise NotImplementedError()
    >>>
    >>> It works but it's tedious, I have to add these 2 lines to every
    >>> virtual method, changing the content of the 2 lines.
    >>>
    >>> Maybe there is a nice/builtin way to do so (python 2.4)
    >>>

    >> Why are you checking which class it's in? The method in the base class
    >> will be called only if it hasn't been overridden in the subclass.

    >
    > Sorry guys (means guys *and* gals :eek:p ), I realized I've not been able
    > to describe precisely what I want to do.
    > I'd like the base class to be virtual (aka abstract). However it may be
    > abstract but it does not mean it cannot do some usefull stuff.
    >
    >
    > Here is the schema of my abstract methods :
    >
    > class Interface(object):
    > def method(self):
    > # ---------------------
    > # some common stuff executed here
    > # ---------------------
    > print 'hello world'
    > # ---------------------
    > # here shall stand child specific stuff (empty in the interface
    > method)
    > # ---------------------
    > if self.__class__.method == Interface.method:
    > raise NotImplementedError('You should have read the f******
    > manual ! You must override this method.')
    >
    > class GoodChild(Interface):
    > def method(self):
    > Interface.method(self) # I want to process the cool stuff done my
    > the base Interface
    > # ------------------------
    > # Specific GoodChild stuff here
    > # ------------------------
    > print 'I am a good'
    > return 'perfect'
    >
    > class BadChild(Interface):
    > pass #I'm too lazy
    >
    >
    > good = GoodChild()
    > bad = BadChild()
    >
    > good.method()
    > ...hello world
    > ...I am a good
    >
    > bad.method()
    > ...NotImplementedError: You should have read the f****** manual ! You
    > must override this method.
    >
    >
    > The reason I'd like to do so: I'll be providing the Interface, but child
    > classes will be overridden by others. Having a reliable error RTFM
    > feedback is a time saver, for me and the users.
    > I hope I clarified my issue.


    First of all, I doubt the above code really yields that output. You are
    missing a super-call there in GoodChild

    And the whole problem goes magically away if you start using OO a bit:


    class Base(object):


    def method(self):
    self._do_some_work_for_method()
    print "some more work"

    def _do_some_work_for_method(self):
    raise NotImplemented


    So your subclasses must implement something else instead of method - and
    voila, without any hassle things work as expected.

    Diez
    Diez B. Roggisch, Aug 14, 2009
    #2
    1. Advertising

  3. Diez B. Roggisch wrote:
    > Jean-Michel Pichavant schrieb:
    >> MRAB wrote:
    >>> Jean-Michel Pichavant wrote:
    >>>> Hi fellows,
    >>>>
    >>>> Does anyone know a way to write virtual methods (in one virtual
    >>>> class) that will raise an exception only if called without being
    >>>> overridden ?
    >>>> Currently in the virtual method I'm checking that the class of the
    >>>> instance calling the method has defined that method as well.
    >>>>
    >>>> Example:
    >>>>
    >>>> class Stream(object):
    >>>> """Interface of all stream objects"""
    >>>> def resetStats(self):
    >>>> """Reset the stream statistics. All values a zeroed except
    >>>> the date."""
    >>>> _log.info('Reset statistics of %s' % self)
    >>>> if self.__class__.resetStats == Stream.resetStats:
    >>>> raise NotImplementedError()
    >>>>
    >>>> It works but it's tedious, I have to add these 2 lines to every
    >>>> virtual method, changing the content of the 2 lines.
    >>>>
    >>>> Maybe there is a nice/builtin way to do so (python 2.4)
    >>>>
    >>> Why are you checking which class it's in? The method in the base class
    >>> will be called only if it hasn't been overridden in the subclass.

    >>
    >> Sorry guys (means guys *and* gals :eek:p ), I realized I've not been
    >> able to describe precisely what I want to do.
    >> I'd like the base class to be virtual (aka abstract). However it may
    >> be abstract but it does not mean it cannot do some usefull stuff.
    >>
    >>
    >> Here is the schema of my abstract methods :
    >>
    >> class Interface(object):
    >> def method(self):
    >> # ---------------------
    >> # some common stuff executed here
    >> # ---------------------
    >> print 'hello world'
    >> # ---------------------
    >> # here shall stand child specific stuff (empty in the
    >> interface method)
    >> # ---------------------
    >> if self.__class__.method == Interface.method:
    >> raise NotImplementedError('You should have read the
    >> f****** manual ! You must override this method.')
    >>
    >> class GoodChild(Interface):
    >> def method(self):
    >> Interface.method(self) # I want to process the cool stuff done
    >> my the base Interface
    >> # ------------------------
    >> # Specific GoodChild stuff here
    >> # ------------------------
    >> print 'I am a good'
    >> return 'perfect'
    >>
    >> class BadChild(Interface):
    >> pass #I'm too lazy
    >>
    >>
    >> good = GoodChild()
    >> bad = BadChild()
    >>
    >> good.method()
    >> ...hello world
    >> ...I am a good
    >>
    >> bad.method()
    >> ...NotImplementedError: You should have read the f****** manual ! You
    >> must override this method.
    >>
    >>
    >> The reason I'd like to do so: I'll be providing the Interface, but
    >> child classes will be overridden by others. Having a reliable error
    >> RTFM feedback is a time saver, for me and the users.
    >> I hope I clarified my issue.

    >
    > First of all, I doubt the above code really yields that output. You
    > are missing a super-call there in GoodChild
    >
    > And the whole problem goes magically away if you start using OO a bit:
    >
    >
    > class Base(object):
    >
    >
    > def method(self):
    > self._do_some_work_for_method()
    > print "some more work"
    >
    > def _do_some_work_for_method(self):
    > raise NotImplemented
    >
    >
    > So your subclasses must implement something else instead of method -
    > and voila, without any hassle things work as expected.
    >
    > Diez


    It does yield that output, there's an unbound call to Interface.method.

    Your solution will work, for sure. The problem is that it will dumb down
    the Base class interface, multiplying the number of methods by 2. This
    would not be an issue in many cases, in mine there's already too much
    meaningful methods in my class for me to add artificial ones.

    Thanks for the tip anyway.
    JM
    Jean-Michel Pichavant, Aug 14, 2009
    #3
  4. Jean-Michel Pichavant

    Nigel Rantor Guest

    Jean-Michel Pichavant wrote:
    >
    > Your solution will work, for sure. The problem is that it will dumb down
    > the Base class interface, multiplying the number of methods by 2. This
    > would not be an issue in many cases, in mine there's already too much
    > meaningful methods in my class for me to add artificial ones.
    >
    > Thanks for the tip anyway.


    I suggest you reconsider.

    You asked a question and have been given a standard way of achieving the
    desired outcome.

    It's common in OO to use a Template pattern like this.

    If you're not interested in finding out how loads of people have already
    solved the problem then why ask?

    The methods that require overriding can be prefixed with an underscore
    so that people get a hint that they are an implementation detail rather
    than part of the public interface.

    I don't see your problem, other than a vague aesthetic unease.

    Regards,

    n
    Nigel Rantor, Aug 14, 2009
    #4
  5. On Fri, 14 Aug 2009 18:49:26 +0200, Jean-Michel Pichavant wrote:

    > Sorry guys (means guys *and* gals :eek:p ), I realized I've not been able
    > to describe precisely what I want to do. I'd like the base class to be
    > virtual (aka abstract). However it may be abstract but it does not mean
    > it cannot do some usefull stuff.
    >
    >
    > Here is the schema of my abstract methods :
    >
    > class Interface(object):
    > def method(self):
    > # ---------------------
    > # some common stuff executed here
    > # ---------------------
    > print 'hello world'
    > # ---------------------
    > # here shall stand child specific stuff (empty in the interface
    > method)
    > # ---------------------
    > if self.__class__.method == Interface.method:
    > raise NotImplementedError('You should have read the f******
    > manual ! You must override this method.')



    Okay, so I want to sub-class your Interface class. As you said, the
    methods in the abstract class are still useful, so in my class, I don't
    need any extra functionality for some methods -- I'm happy with just the
    "common stuff". So I use normal OO techniques and over-ride just the
    methods I need to over-ride:

    class GoodChild(Interface):
    # no need to over-ride method, because it does everything I want
    # but over-ride other methods that don't
    def whatever(self):
    print "Whatever..."
    return Interface.whatever()

    But now my class fails, with an insulting error message *wink*, and you
    force me to write a whole lot of crappy stupid boilerplate code:

    class VerboseGoodChild(Interface):
    # forced to over-ride methods for no good reason
    def method(self):
    return Interface.method(self)
    def another_method(self):
    return Interface.another_method(self)
    def yet_another_method(self):
    return Interface.yet_another_method(self)
    def still_more_methods(self):
    return Interface.still_more_methods(self)
    # Whew! That was a waste of effort. Now at last over-ride the
    # methods I need to:
    def whatever(self):
    print "Whatever..."
    return Interface.whatever()

    After the fourth such class, I say "Bugger this for a game of soldiers"
    and dump your Interface class for something else.


    > The reason I'd like to do so: I'll be providing the Interface, but child
    > classes will be overridden by others. Having a reliable error RTFM
    > feedback is a time saver, for me and the users. I hope I clarified my
    > issue.


    The usual way of implementing abstract base classes is to simply prohibit
    instantiation of the class, but allow all other inheritance. Putting
    useful functionality in methods, but then prohibiting subclasses from
    using them without jumping through hoops first, seems rather perverse to
    me.



    --
    Steven
    Steven D'Aprano, Aug 14, 2009
    #5
  6. Nigel Rantor wrote:
    > Jean-Michel Pichavant wrote:
    >>
    >> Your solution will work, for sure. The problem is that it will dumb
    >> down the Base class interface, multiplying the number of methods by
    >> 2. This would not be an issue in many cases, in mine there's already
    >> too much meaningful methods in my class for me to add artificial ones.
    >>
    >> Thanks for the tip anyway.

    >
    > I suggest you reconsider.
    >
    > You asked a question and have been given a standard way of achieving
    > the desired outcome.
    >
    > It's common in OO to use a Template pattern like this.
    >
    > If you're not interested in finding out how loads of people have
    > already solved the problem then why ask?
    >
    > The methods that require overriding can be prefixed with an underscore
    > so that people get a hint that they are an implementation detail
    > rather than part of the public interface.
    >
    > I don't see your problem, other than a vague aesthetic unease.
    >
    > Regards,
    >
    > n

    I understand how refuting some obvious solution may look just stupid.
    You're right, I shouldn't have asked.

    By the way I'd like to know if I am I alone to find that

    class Stream:
    def start
    def stop
    def reset

    is better than

    class Stream:
    def start
    def _start
    def stop
    def _stop
    def reset
    def _reset

    (try to figure out with 20+ methods)
    What you call aesthetic may sometimes fall into readability.


    JM
    Jean-Michel Pichavant, Aug 14, 2009
    #6
  7. Jean-Michel Pichavant

    Nigel Rantor Guest

    Jean-Michel Pichavant wrote:
    > Nigel Rantor wrote:
    >> Jean-Michel Pichavant wrote:
    >>>
    >>> Your solution will work, for sure. The problem is that it will dumb
    >>> down the Base class interface, multiplying the number of methods by
    >>> 2. This would not be an issue in many cases, in mine there's already
    >>> too much meaningful methods in my class for me to add artificial ones.
    >>>
    >>> Thanks for the tip anyway.

    >>
    >> I suggest you reconsider.
    >>
    >> You asked a question and have been given a standard way of achieving
    >> the desired outcome.
    >>
    >> It's common in OO to use a Template pattern like this.
    >>
    >> If you're not interested in finding out how loads of people have
    >> already solved the problem then why ask?
    >>
    >> The methods that require overriding can be prefixed with an underscore
    >> so that people get a hint that they are an implementation detail
    >> rather than part of the public interface.
    >>
    >> I don't see your problem, other than a vague aesthetic unease.
    >>
    >> Regards,
    >>
    >> n

    > I understand how refuting some obvious solution may look just stupid.
    > You're right, I shouldn't have asked.


    I never said it seemed stupid. I was merely curious as to why you'd ask
    a question and ignore solutions.

    > By the way I'd like to know if I am I alone to find that
    >
    > class Stream:
    > def start
    > def stop
    > def reset
    >
    > is better than
    >
    > class Stream:
    > def start
    > def _start
    > def stop
    > def _stop
    > def reset
    > def _reset
    >
    > (try to figure out with 20+ methods)
    > What you call aesthetic may sometimes fall into readability.


    Depends on what you mean by "better".

    Do you mean pleasing to your eye or performs the task you want it to?

    Assuming you are taking the aesthetic viewpoint I think that in this
    case it will depend on how you set out your code.

    Realise that all of the underscore methods for your class are
    boilerplate, they simply raise an exception.

    They can all be at the end of the file, commented as an entire block to
    be left alone.

    Editing the main body of code is then fairly easy, and uncluttered...

    e.g.

    #
    # Stream class blah blah blah
    #
    class Stream:

    def start

    def stop

    def reset

    #
    # stubs to be over-ridden in sub-classes, add one for each
    # method that requires overriding.
    #
    def _start
    def _stop
    def _reset

    Regards,

    Nigel

    p.s. Please take this in the spirit it is offered. I'm trying to stop
    you from ignoring a good suggestion, not make you feel like a fool.
    Nigel Rantor, Aug 14, 2009
    #7
  8. Jean-Michel Pichavant

    Dave Angel Guest

    Jean-Michel Pichavant wrote:
    > <div class="moz-text-flowed" style="font-family: -moz-fixed">Nigel
    > Rantor wrote:
    >> Jean-Michel Pichavant wrote:
    >>>
    >>> Your solution will work, for sure. The problem is that it will dumb
    >>> down the Base class interface, multiplying the number of methods by
    >>> 2. This would not be an issue in many cases, in mine there's already
    >>> too much meaningful methods in my class for me to add artificial ones.
    >>>
    >>> Thanks for the tip anyway.

    >>
    >> I suggest you reconsider.
    >>
    >> You asked a question and have been given a standard way of achieving
    >> the desired outcome.
    >>
    >> It's common in OO to use a Template pattern like this.
    >>
    >> If you're not interested in finding out how loads of people have
    >> already solved the problem then why ask?
    >>
    >> The methods that require overriding can be prefixed with an
    >> underscore so that people get a hint that they are an implementation
    >> detail rather than part of the public interface.
    >>
    >> I don't see your problem, other than a vague aesthetic unease.
    >>
    >> Regards,
    >>
    >> n

    > I understand how refuting some obvious solution may look just stupid.
    > You're right, I shouldn't have asked.
    >
    > By the way I'd like to know if I am I alone to find that
    >
    > class Stream:
    > def start
    > def stop
    > def reset
    >
    > is better than
    >
    > class Stream:
    > def start
    > def _start
    > def stop
    > def _stop
    > def reset
    > def _reset
    >
    > (try to figure out with 20+ methods)
    > What you call aesthetic may sometimes fall into readability.
    >
    >
    > JM
    >
    >
    > </div>
    >

    Usually when one defines an abstract base class, one expects many people
    will derive from it, as opposed to only one having to write it. So if
    the base must be "ugly" according to some definition, so be it.
    Aesthetics are quite subjective.

    Nigel's approach has another benefit not stated, which is to keep the
    child class code simpler. They avoid the need to call any base class
    method to access the common logic. The downside is it assumes that the
    common logic will always be either at the beginning or always at the end
    of the child classes implementation. That's because the base class has
    hardcoded where in its implementation to call the child class method.

    Anyway, without arguing for or against either approach, I'd point out
    that you could have an extra formal parameter in the base method, which
    is a private signal from the child class that this is the internal
    call. Missing such a formal parameter would then trigger the "missing
    method in derived class" error message. You'd check such a parameter
    the same place as you're now checking the object's type.

    DaveA
    Dave Angel, Aug 14, 2009
    #8
  9. Steven D'Aprano wrote:
    > On Fri, 14 Aug 2009 18:49:26 +0200, Jean-Michel Pichavant wrote:
    >
    >
    >> Sorry guys (means guys *and* gals :eek:p ), I realized I've not been able
    >> to describe precisely what I want to do. I'd like the base class to be
    >> virtual (aka abstract). However it may be abstract but it does not mean
    >> it cannot do some usefull stuff.
    >>
    >>
    >> Here is the schema of my abstract methods :
    >>
    >> class Interface(object):
    >> def method(self):
    >> # ---------------------
    >> # some common stuff executed here
    >> # ---------------------
    >> print 'hello world'
    >> # ---------------------
    >> # here shall stand child specific stuff (empty in the interface
    >> method)
    >> # ---------------------
    >> if self.__class__.method == Interface.method:
    >> raise NotImplementedError('You should have read the f******
    >> manual ! You must override this method.')
    >>

    >
    >
    > Okay, so I want to sub-class your Interface class. As you said, the
    > methods in the abstract class are still useful, so in my class, I don't
    > need any extra functionality for some methods -- I'm happy with just the
    > "common stuff". So I use normal OO techniques and over-ride just the
    > methods I need to over-ride:
    >
    >

    Sometimes the base is doing cool stuff but incomplete stuff which
    requires knowledge only hold by the sub class. In my case the interface
    is a high level interface for a software that can run on multiple
    hardware platforms. Only the sub class has knowledge on how to operate
    the hardware, but no matter the hardware it still produces the same effect.

    Let's say I have 50 different hardwares, I'll have 50 sub classes of
    Interface with the 'start' method to define. It wouldn't be appropriate
    (OO programming)to write 50 times '_log.debug('Starting %s' % self)' in
    each child start method when the simple task of logging the call can be
    nicely handled by the base class.

    In the meantime, I must make sure the user, who is not a python guru in
    this case, has implemented the start method for his hardware, because
    only him knows how to effectively start this hardware. I don't want him
    to come to me saying, "I got no error, still my hardware does not
    start". You can then blame him for not reading the docs, but it will
    still be less expensive to throw a nice exception with an accurate feedback.

    [snip]
    > class VerboseGoodChild(Interface):
    > # forced to over-ride methods for no good reason
    >


    Definitely no !! This is the purpose of an interface class: to force
    people to write these methods. They *are* required, if they were not,
    they would not belong to the Interface.

    JM
    Jean-Michel Pichavant, Aug 14, 2009
    #9
  10. Dave Angel wrote:
    > Jean-Michel Pichavant wrote:
    >> <div class="moz-text-flowed" style="font-family: -moz-fixed">Nigel
    >> Rantor wrote:
    >>> Jean-Michel Pichavant wrote:
    >>>>
    >>>> Your solution will work, for sure. The problem is that it will dumb
    >>>> down the Base class interface, multiplying the number of methods by
    >>>> 2. This would not be an issue in many cases, in mine there's
    >>>> already too much meaningful methods in my class for me to add
    >>>> artificial ones.
    >>>>
    >>>> Thanks for the tip anyway.
    >>>
    >>> I suggest you reconsider.
    >>>
    >>> You asked a question and have been given a standard way of achieving
    >>> the desired outcome.
    >>>
    >>> It's common in OO to use a Template pattern like this.
    >>>
    >>> If you're not interested in finding out how loads of people have
    >>> already solved the problem then why ask?
    >>>
    >>> The methods that require overriding can be prefixed with an
    >>> underscore so that people get a hint that they are an implementation
    >>> detail rather than part of the public interface.
    >>>
    >>> I don't see your problem, other than a vague aesthetic unease.
    >>>
    >>> Regards,
    >>>
    >>> n

    >> I understand how refuting some obvious solution may look just stupid.
    >> You're right, I shouldn't have asked.
    >>
    >> By the way I'd like to know if I am I alone to find that
    >>
    >> class Stream:
    >> def start
    >> def stop
    >> def reset
    >>
    >> is better than
    >>
    >> class Stream:
    >> def start
    >> def _start
    >> def stop
    >> def _stop
    >> def reset
    >> def _reset
    >>
    >> (try to figure out with 20+ methods)
    >> What you call aesthetic may sometimes fall into readability.
    >>
    >>
    >> JM
    >>
    >>
    >> </div>
    >>

    > Usually when one defines an abstract base class, one expects many
    > people will derive from it, as opposed to only one having to write
    > it. So if the base must be "ugly" according to some definition, so be
    > it. Aesthetics are quite subjective.
    >
    > Nigel's approach has another benefit not stated, which is to keep the
    > child class code simpler. They avoid the need to call any base class
    > method to access the common logic. The downside is it assumes that
    > the common logic will always be either at the beginning or always at
    > the end of the child classes implementation. That's because the base
    > class has hardcoded where in its implementation to call the child
    > class method.
    >

    I think this is a severe issue.
    You prevent the sub class from writing
    def foo(self):
    pre()
    Base.foo(self)
    post()
    > Anyway, without arguing for or against either approach, I'd point out
    > that you could have an extra formal parameter in the base method,
    > which is a private signal from the child class that this is the
    > internal call. Missing such a formal parameter would then trigger the
    > "missing method in derived class" error message. You'd check such a
    > parameter the same place as you're now checking the object's type.
    >
    > DaveA
    >
    >



    talking about approaches:

    1/
    class Interface:
    def foo(self):
    if self.__class__.foo == Interface.foo:
    raise NotImplementedError

    2/
    class Interface:
    def foo(self):
    self._foo()

    def _foo(sef):
    raise NotImplementedError

    Are they so different ? They both require about the same amount of extra
    characters, they're both readable. The second is a very classic OO
    layout, the first is more flexible for the sub classes and spare some
    method definition.

    This thread may live again, I cannot say but I'd like to thanks all who
    gave me their valuable idea on the subject, I mean it. Please don't take
    my skepticism as a lack of consideration.

    JM
    Jean-Michel Pichavant, Aug 14, 2009
    #10
  11. Scott David Daniels wrote:
    > Jean-Michel Pichavant wrote:
    >> Steven D'Aprano wrote:
    >>> On Fri, 14 Aug 2009 18:49:26 +0200, Jean-Michel Pichavant wrote:
    >>>
    >>>
    >>>> Sorry guys (means guys *and* gals :eek:p ), I realized I've not been able
    >>>> to describe precisely what I want to do. I'd like the base class to be
    >>>> virtual (aka abstract). However it may be abstract but it does not
    >>>> mean
    >>>> it cannot do some usefull stuff.
    >>>>
    >>>>
    >>>> Here is the schema of my abstract methods :
    >>>>
    >>>> class Interface(object):
    >>>> def method(self):
    >>>> # ---------------------
    >>>> # some common stuff executed here
    >>>> # ---------------------
    >>>> print 'hello world'
    >>>> # ---------------------
    >>>> # here shall stand child specific stuff (empty in the
    >>>> interface
    >>>> method)
    >>>> # ---------------------
    >>>> if self.__class__.method == Interface.method:
    >>>> raise NotImplementedError('You should have read the
    >>>> f******
    >>>> manual ! You must override this method.')
    >>>>
    >>>
    >>>
    >>> Okay, so I want to sub-class your Interface class. As you said, the
    >>> methods in the abstract class are still useful, so in my class, I
    >>> don't need any extra functionality for some methods -- I'm happy
    >>> with just the "common stuff". So I use normal OO techniques and
    >>> over-ride just the methods I need to over-ride:
    >>>
    >>>

    >> Sometimes the base is doing cool stuff but incomplete stuff which
    >> requires knowledge only hold by the sub class. In my case the
    >> interface is a high level interface for a software that can run on
    >> multiple hardware platforms. Only the sub class has knowledge on how
    >> to operate the hardware, but no matter the hardware it still produces
    >> the same effect.
    >>
    >> Let's say I have 50 different hardwares, I'll have 50 sub classes of
    >> Interface with the 'start' method to define. It wouldn't be
    >> appropriate (OO programming)to write 50 times '_log.debug('Starting
    >> %s' % self)' in each child start method when the simple task of
    >> logging the call can be nicely handled by the base class.
    >>
    >> In the meantime, I must make sure the user, who is not a python guru
    >> in this case, has implemented the start method for his hardware,
    >> because only him knows how to effectively start this hardware. I
    >> don't want him to come to me saying, "I got no error, still my
    >> hardware does not start". You can then blame him for not reading the
    >> docs, but it will still be less expensive to throw a nice exception
    >> with an accurate feedback.
    >>
    >> [snip]
    >>> class VerboseGoodChild(Interface):
    >>> # forced to over-ride methods for no good reason
    >>>

    >>
    >> Definitely no !! This is the purpose of an interface class: to force
    >> people to write these methods. They *are* required, if they were not,
    >> they would not belong to the Interface.
    >>
    >> JM

    >
    > But there _is_ one moment when you can check those things, then avoid
    > checking thereafter: object creation. So you can complicate your
    > __init__ (or __new__) with those checks that make sure you instantiate
    > only fully defined subclasses:
    >
    > # obviously not tested except in concept:
    >
    > class Base(object_or_whatever):
    > def __init__(self, ...):
    > class_ = self.__class__
    > if class_ is Base:
    > raise TypeError('Attempt to instantiate Base class')
    > for name in 'one two three four':
    > if getattr(Base, name) is not getattr(Base, name):
    > raise NotImplementedError(
    > '%s implementation missing' % name)
    > ...
    >
    > --Scott David Daniels
    >

    That could do the trick, sparing me from writing additional code in each
    methods. Thanks.

    JM
    Jean-Michel Pichavant, Aug 16, 2009
    #11
  12. Jean-Michel Pichavant a écrit :
    (snip)

    > Sometimes the base is doing cool stuff but incomplete stuff which
    > requires knowledge only hold by the sub class. In my case the interface
    > is a high level interface for a software that can run on multiple
    > hardware platforms. Only the sub class has knowledge on how to operate
    > the hardware, but no matter the hardware it still produces the same effect.
    >
    > Let's say I have 50 different hardwares, I'll have 50 sub classes of
    > Interface with the 'start' method to define. It wouldn't be appropriate
    > (OO programming)to write 50 times '_log.debug('Starting %s' % self)' in
    > each child start method when the simple task of logging the call can be
    > nicely handled by the base class.


    Which is exactly one of the use cases for the Template Method pattern in
    traditional OO design.

    For the record, Python can offer other solutions to this kind of problem
    - like a combination of decorators and metaclasses.

    > In the meantime, I must make sure the user, who is not a python guru in
    > this case, has implemented the start method for his hardware,


    whether he has to implement the 'start' or '_start' method doesn't make
    any difference here.
    Bruno Desthuilliers, Aug 17, 2009
    #12
  13. Jean-Michel Pichavant a écrit :
    > Scott David Daniels wrote:

    (snip)
    >> But there _is_ one moment when you can check those things, then avoid
    >> checking thereafter: object creation. So you can complicate your
    >> __init__ (or __new__) with those checks that make sure you instantiate
    >> only fully defined subclasses:


    That's something I'd rather do in a custom metaclass. But YMMV, of course...
    Bruno Desthuilliers, Aug 17, 2009
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jlopes
    Replies:
    7
    Views:
    402
    jlopes
    Nov 19, 2004
  2. Edward Diener

    Static method object not callable

    Edward Diener, Aug 11, 2004, in forum: Python
    Replies:
    8
    Views:
    667
    gblandst
    Mar 27, 2008
  3. exiquio
    Replies:
    2
    Views:
    515
    exiquio
    Oct 7, 2008
  4. Jean-Michel Pichavant

    callable virtual method

    Jean-Michel Pichavant, Aug 14, 2009, in forum: Python
    Replies:
    2
    Views:
    315
    Steven D'Aprano
    Aug 14, 2009
  5. Ulrich Eckhardt
    Replies:
    6
    Views:
    90
    Peter Otten
    Jul 12, 2013
Loading...

Share This Page