Can a base class know if a method has been overridden?

Discussion in 'Python' started by Bruno Desthuilliers, Sep 22, 2007.

  1. Ratko a écrit :
    > bruno a écrit
    >>Another solution is to compare the functions wrapped by the methods:
    >>
    >>class EvtHandler:
    >> def __init__(self):
    >> onKey = getattr(self, 'onKey')
    >> if onKey.im_func is EvtHandler.onKey.im_func:


    s/is/is not/, of course

    >> register_for_key_events()
    >>
    >> def onKey(self):
    >> pass
    >>
    >>class MyHandler(EvtHandler):
    >> def onKey(self):
    >> # do something here....
    >>
    >>HTH

    >
    >
    > The second solution works beautifully!


    Hem... Almost !-)

    > Thank you very much.
    > I was aware that not implementing the onKey method in the first place
    > is the simplest solution but it's much cleaner to offer the methods in
    > advance so that the user can see what is possible.


    Yeps - a placeholder 'abstract' method with only a docstring. It's a
    common pattern in frameworks, but usually it's just an ordinary template
    method pattern defaulting to a no-op.

    FWIW, if you have several such methods to handle, you can use a more
    generic approach:

    _handlers = {
    'onKey':registerForKeyEvents,
    'onClick':registerForMouseEvents,
    } # etc

    class EventHandler(object):
    for _name in _handlers:
    exec "%s=lambda self, *args, **kw: pass" % _name

    def __new__(cls, *args, **kw):
    obj = object.__new__(cls, *args, **kw)
    for name, register_func in _handlers.items():
    meth = getattr(obj, name)
    dummy = getattr(EventHandler, name)
    if meth.im_func is not dummy.im_func:
    register_func(meth)
    return obj


    HTH
    Bruno Desthuilliers, Sep 22, 2007
    #1
    1. Advertising

  2. Bruno Desthuilliers

    Ratko Guest

    Hi all,

    I was wondering if something like this is possible. Can a base class
    somehow know if a certain method has been overridden by the subclass?
    I appreciate any ideas.
    Thanks,

    Ratko
    Ratko, Sep 24, 2007
    #2
    1. Advertising

  3. Ratko a écrit :
    > Hi all,
    >
    > I was wondering if something like this is possible. Can a base class
    > somehow know if a certain method has been overridden by the subclass?


    If your use case is to make sure a given ('abstract') method has been
    overriden, the canonical solution is to raise NotImplementedError in the
    base class's implementation, ie:


    class Parent(object):
    def method(self):
    raise NotImplementedError

    class GoodGirl(Parent):
    def method(self):
    print "I'm a good girl"

    class BadBoy(Parent):
    pass


    Else, this may be possible using a custom metaclass (or possibly just
    specializing the __new__ method), but there may be better solutions
    (depending on what you're really trying to do)..

    HTH
    Bruno Desthuilliers, Sep 24, 2007
    #3
  4. On Sep 24, 5:23 pm, Ratko <> wrote:
    > Hi all,
    >
    > I was wondering if something like this is possible. Can a base class
    > somehow know if a certain method has been overridden by the subclass?
    > I appreciate any ideas.
    > Thanks,
    >
    > Ratko



    The first time I used Zope, I immediately had an issue of overriding a
    predefined
    methods without knowing it (there were 400+ methods inherited from
    dozens of base
    classes). So I wrote this utility:


    def check_if_I_am_overriding_names():
    """Prints a message if we are overriding a name. Useful for
    framework
    beginners. Example in Zope:

    >> from OFS.Folder import Folder
    >> class MyFolder(OFS.Folder):

    .. check_if_I_am_overriding_names()
    .. id = 'pippo'
    ..
    AlreadyDefinedNameWarning: id
    """

    def makecls(name, bases, dic):
    for nam, val in dic.iteritems():
    if nam.endswith("__") or nam == "meta_types":
    # ignore redefinitions of special names
    # and redefinition of meta_types (for Zope code)
    continue
    any_base_has_name = [base for base in bases
    if hasattr(base, nam)]
    if any_base_has_name:
    print "AlreadyDefinedNameWarning: " + nam
    return type(name, bases, dic)

    f = sys._getframe(1)
    f.f_locals["__metaclass__"] = makecls

    Michele Simionato
    Michele Simionato, Sep 24, 2007
    #4
  5. Bruno Desthuilliers

    Ratko Guest

    > If your use case is to make sure a given ('abstract') method has been
    > overriden, the canonical solution is to raise NotImplementedError in the
    > base class's implementation


    I am not really interested in forcing the subclass to implement a
    method. I am interested in knowing *whether* it did implement it or
    not.


    > Else, this may be possible using a custom metaclass (or possibly just
    > specializing the __new__ method), but there may be better solutions
    > (depending on what you're really trying to do)..


    I have a base class EvtHandler that has methods defined to handle
    certain events. You then subclass from EvtHandler and override the
    methods for the events you want to receive. If a method has been
    overridden, the base class will automatically register for those
    events to make sure that they are even delivered to this handler
    (which is why I would need to know whether a method has been
    overridden or not). Of course, there are other ways of doing this
    which would require a bit more work from the subclass... I just
    thought this would be a neat "automatic" way of registering for
    events.

    For example:

    class EvtHandler:
    def __init__(self):
    if onKey is overridden:
    register_for_key_events()

    def onKey(self):
    pass


    class MyHandler(EvtHandler):
    def onKey(self):
    # do something here....
    Ratko, Sep 24, 2007
    #5
  6. On Mon, 24 Sep 2007 15:48:07 +0000, Ratko wrote:

    > I have a base class EvtHandler that has methods defined to handle
    > certain events. You then subclass from EvtHandler and override the
    > methods for the events you want to receive. If a method has been
    > overridden, the base class will automatically register for those
    > events to make sure that they are even delivered to this handler
    > (which is why I would need to know whether a method has been
    > overridden or not). Of course, there are other ways of doing this
    > which would require a bit more work from the subclass... I just
    > thought this would be a neat "automatic" way of registering for
    > events.
    >
    > For example:
    >
    > class EvtHandler:
    > def __init__(self):
    > if onKey is overridden:
    > register_for_key_events()
    >
    > def onKey(self):
    > pass
    >
    >
    > class MyHandler(EvtHandler):
    > def onKey(self):
    > # do something here....


    Maybe "tagging" the original `on_key()`:

    class EvtHandler:
    def __init__(self):
    if not hasattr(self.on_key, 'dummy'):
    print 'register_for_key_events()'

    def _dummy_handler(self):
    pass
    _dummy_handler.dummy = True

    on_key = _dummy_handler
    on_whatever = _dummy_handler


    class MyHandler(EvtHandler):
    def on_key(self):
    print 'Do something...'

    Ciao,
    Marc 'BlackJack' Rintsch
    Marc 'BlackJack' Rintsch, Sep 24, 2007
    #6
  7. Bruno Desthuilliers

    Chris Mellon Guest

    On 9/24/07, Ratko <> wrote:
    > > If your use case is to make sure a given ('abstract') method has been
    > > overriden, the canonical solution is to raise NotImplementedError in the
    > > base class's implementation

    >
    > I am not really interested in forcing the subclass to implement a
    > method. I am interested in knowing *whether* it did implement it or
    > not.
    >
    >
    > > Else, this may be possible using a custom metaclass (or possibly just
    > > specializing the __new__ method), but there may be better solutions
    > > (depending on what you're really trying to do)..

    >
    > I have a base class EvtHandler that has methods defined to handle
    > certain events. You then subclass from EvtHandler and override the
    > methods for the events you want to receive. If a method has been
    > overridden, the base class will automatically register for those
    > events to make sure that they are even delivered to this handler
    > (which is why I would need to know whether a method has been
    > overridden or not). Of course, there are other ways of doing this
    > which would require a bit more work from the subclass... I just
    > thought this would be a neat "automatic" way of registering for
    > events.
    >
    > For example:
    >
    > class EvtHandler:
    > def __init__(self):
    > if onKey is overridden:
    > register_for_key_events()
    >
    > def onKey(self):
    > pass
    >
    >
    > class MyHandler(EvtHandler):
    > def onKey(self):
    > # do something here....


    Clumsy, but it seems to work. Using a sentinel value as Marc Rintsch
    suggests might be better:

    >>> class A(object):

    .... def vMethod(self, x):
    .... raise NotImplemented
    .... def is_implemented(self, method):
    .... if getattr(type(self), method.__name__).im_func is not
    method.im_func:
    .... return True
    .... def otherMethod(self, x):
    .... raise NotImplemented
    ....
    >>> class B(A):

    .... def vMethod(self, x):
    .... print x
    ....
    >>> b = b()

    Traceback (most recent call last):
    File "<input>", line 1, in <module>
    TypeError: 'B' object is not callable
    >>> b = B()
    >>> b.otherMethod(10)

    Traceback (most recent call last):
    File "<input>", line 1, in <module>
    File "<input>", line 8, in otherMethod
    TypeError: exceptions must be classes, instances, or strings
    (deprecated), not NotImplementedType
    >>> b.vMethod(10)

    10
    >>> b.is_implemented(A.vMethod)

    True
    >>> b.is_implemented(A.otherMethod)
    >>>



    (Note that I accidentally raised NotImplemented instead of
    NotImplementedError, oops.)
    Chris Mellon, Sep 24, 2007
    #7
  8. Ratko a écrit :
    >> If your use case is to make sure a given ('abstract') method has been
    >> overriden, the canonical solution is to raise NotImplementedError in the
    >> base class's implementation

    >
    > I am not really interested in forcing the subclass to implement a
    > method. I am interested in knowing *whether* it did implement it or
    > not.
    >
    >
    >> Else, this may be possible using a custom metaclass (or possibly just
    >> specializing the __new__ method), but there may be better solutions
    >> (depending on what you're really trying to do)..

    >
    > I have a base class EvtHandler that has methods defined to handle
    > certain events. You then subclass from EvtHandler and override the
    > methods for the events you want to receive. If a method has been
    > overridden, the base class will automatically register for those
    > events to make sure that they are even delivered to this handler
    > (which is why I would need to know whether a method has been
    > overridden or not). Of course, there are other ways of doing this
    > which would require a bit more work from the subclass... I just
    > thought this would be a neat "automatic" way of registering for
    > events.
    >
    > For example:
    >
    > class EvtHandler:
    > def __init__(self):
    > if onKey is overridden:
    > register_for_key_events()
    >
    > def onKey(self):
    > pass
    >
    >
    > class MyHandler(EvtHandler):
    > def onKey(self):
    > # do something here....
    >


    Ok. The simplest solution, then, is simply to not implement the method
    in the base class, ie:

    class EvtHandler:
    def __init__(self):
    if hasattr(self, 'onKey'):
    register_for_key_events()

    #def onKey(self):
    # pass


    class MyHandler(EvtHandler):
    def onKey(self):
    # do something here....


    Another solution is to compare the functions wrapped by the methods:

    class EvtHandler:
    def __init__(self):
    onKey = getattr(self, 'onKey')
    if onKey.im_func is EvtHandler.onKey.im_func:
    register_for_key_events()

    def onKey(self):
    pass


    class MyHandler(EvtHandler):
    def onKey(self):
    # do something here....


    HTH
    Bruno Desthuilliers, Sep 24, 2007
    #8
  9. What about something like:

    class A(object):
    def my_method(self):
    print "A.my_method"
    def call_my_method(self):
    if type(self).my_method == A.my_method:
    print "Calling base class method."
    else:
    print "Calling derived class method."
    self.my_method()

    class B(A):
    pass

    class C(A):
    def my_method(self):
    print "C.my_method"

    a = A()
    b = B()
    c = C()

    a.call_my_method()
    b.call_my_method()
    c.call_my_method()


    Stéphane
    =?utf-8?b?U3TDqXBoYW5l?= Larouche, Sep 24, 2007
    #9
  10. Bruno Desthuilliers

    Ratko Guest

    > Ok. The simplest solution, then, is simply to not implement the method
    > in the base class, ie:
    >
    > class EvtHandler:
    > def __init__(self):
    > if hasattr(self, 'onKey'):
    > register_for_key_events()
    >
    > #def onKey(self):
    > # pass
    >
    > class MyHandler(EvtHandler):
    > def onKey(self):
    > # do something here....
    >
    > Another solution is to compare the functions wrapped by the methods:
    >
    > class EvtHandler:
    > def __init__(self):
    > onKey = getattr(self, 'onKey')
    > if onKey.im_func is EvtHandler.onKey.im_func:
    > register_for_key_events()
    >
    > def onKey(self):
    > pass
    >
    > class MyHandler(EvtHandler):
    > def onKey(self):
    > # do something here....
    >
    > HTH


    The second solution works beautifully! Thank you very much.
    I was aware that not implementing the onKey method in the first place
    is the simplest solution but it's much cleaner to offer the methods in
    advance so that the user can see what is possible.

    Ratko
    Ratko, Sep 24, 2007
    #10
  11. Bruno Desthuilliers

    Ratko Guest

    On Sep 24, 12:56 pm, Stéphane Larouche <>
    wrote:
    > What about something like:
    >
    > class A(object):
    > def my_method(self):
    > print "A.my_method"
    > def call_my_method(self):
    > if type(self).my_method == A.my_method:
    > print "Calling base class method."
    > else:
    > print "Calling derived class method."
    > self.my_method()
    >
    > class B(A):
    > pass
    >
    > class C(A):
    > def my_method(self):
    > print "C.my_method"
    >
    > a = A()
    > b = B()
    > c = C()
    >
    > a.call_my_method()
    > b.call_my_method()
    > c.call_my_method()
    >
    > Stéphane



    I think it would confuse the user to have to call "call_my_method" as
    opposed to calling "my_method" directly. The only reason why I wanted
    to do this is simplicity, clarity and transparency. Thanks though.
    Bruno's solution does exactly what I was looking for.

    Ratko
    Ratko, Sep 24, 2007
    #11
  12. Ratko wrote:
    > I was wondering if something like this is possible. Can a base class
    > somehow know if a certain method has been overridden by the subclass?


    You can try using the __subclasses__() method on the class::

    >>> def is_overridden(method):

    ... for cls in method.im_class.__subclasses__():
    ... func = cls.__dict__.get(method.__name__)
    ... if func is not None and func != method.im_func:
    ... return True
    ... return False
    ...
    >>> class A(object):

    ... def foo(self):
    ... return 'A.foo'
    ... def bar(self):
    ... return 'A.bar'
    ...
    >>> class B(A):

    ... def foo(self):
    ... return 'B.foo'
    ...
    >>> is_overridden(A.foo)

    True
    >>> is_overridden(A.bar)

    False

    Given a method from the base class, is_overridden gets the base class,
    and then looks through every subclass of that class. If the function
    object for the subclass is ever different from that of the base class,
    then the base class's method must have been overridden.

    STeVe
    Steven Bethard, Sep 24, 2007
    #12
  13. On Sep 24, 8:23 am, Ratko <> wrote:
    > Hi all,
    >
    > I was wondering if something like this is possible. Can a base class
    > somehow know if a certain method has been overridden by the subclass?
    > I appreciate any ideas.
    > Thanks,
    >
    > Ratko



    It's not hard. Both bound and unbound methods have an im_func
    attribute pointing to the underlying function code. So you can check
    for overrides by testing whether the underlying functions are the
    same:

    >>> class A:

    def p(self): pass
    def q(self): pass


    >>> class B(A):

    def q(self): pass


    >>> b = B()
    >>> b.p.im_func is A.p.im_func # Verify that b.p runs A.p

    True
    >>> b.q.im_func is A.q.im_func # Verify that b.q overrides A.q




    Raymond

    False
    Raymond Hettinger, Sep 24, 2007
    #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. Patel
    Replies:
    6
    Views:
    40,490
    Randall R Schulz
    Oct 23, 2003
  2. Patel
    Replies:
    1
    Views:
    405
    Harald Hein
    Oct 23, 2003
  3. S. I. Becker
    Replies:
    11
    Views:
    533
    Earl Purple
    Jun 14, 2006
  4. wink
    Replies:
    4
    Views:
    1,164
  5. Replies:
    2
    Views:
    109
Loading...

Share This Page