Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Can a base class know if a method has been overridden?

Reply
Thread Tools

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

 
 
Bruno Desthuilliers
Guest
Posts: n/a
 
      09-22-2007
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
 
Reply With Quote
 
 
 
 
Ratko
Guest
Posts: n/a
 
      09-24-2007
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

 
Reply With Quote
 
 
 
 
Bruno Desthuilliers
Guest
Posts: n/a
 
      09-24-2007
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
 
Reply With Quote
 
Michele Simionato
Guest
Posts: n/a
 
      09-24-2007
On Sep 24, 5:23 pm, Ratko <(E-Mail Removed)> 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

 
Reply With Quote
 
Ratko
Guest
Posts: n/a
 
      09-24-2007
> 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....

 
Reply With Quote
 
Marc 'BlackJack' Rintsch
Guest
Posts: n/a
 
      09-24-2007
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
 
Reply With Quote
 
Chris Mellon
Guest
Posts: n/a
 
      09-24-2007
On 9/24/07, Ratko <(E-Mail Removed)> 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.)
 
Reply With Quote
 
Bruno Desthuilliers
Guest
Posts: n/a
 
      09-24-2007
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
 
Reply With Quote
 
=?utf-8?b?U3TDqXBoYW5l?= Larouche
Guest
Posts: n/a
 
      09-24-2007
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



 
Reply With Quote
 
Ratko
Guest
Posts: n/a
 
      09-24-2007
> 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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Base class method Need base class value Karan Rajput Ruby 2 12-22-2010 04:47 PM
why a class can't access protected method from another class in thesame package,the method is interited from the ohtner class from differntpackage? junzhang1983@gmail.com Java 3 01-28-2008 02:09 AM
know can I know how much object has been created??? sayoyo@yahoo.com Ruby 2 03-31-2006 08:09 PM
The printing has been stopped and this job has been add to the queu? dejola Computer Support 6 12-30-2005 03:26 AM
How can we know if a HttpServletResponse has been redirected ? Bruno Thomas Java 2 09-13-2005 02:47 PM



Advertisments