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)
JM
Python has no concept of "virtual" methods. A simple
class Stream(object):
def resetStats(self):
raise NotImplemented
is all you need. Once a subclass overrides resetStats, that
implementatino is used.
Additionally, there are modules such as zope.interface out there, that
let you define more formally what an interface is, and declare who's
implementing it. I don't used this myself though, so I can't really
comment to which extend it e.g. warns you if you subclass *without*
implementing.
Diez
> 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.
I'm not entirely sure of the terminology -- is this the same as an
abstract base class? Googling has not enlightened me. Given your example,
it seems to be.
> 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()
The usual idiom I've seen for abstract methods is to simplify the check,
and to put it *before* any work is done:
class Stream(object):
"""Interface of all stream objects"""
def resetStats(self):
if self.__class__ is Stream:
raise NotImplementedError()
_log.info('Reset statistics of %s' % self)
Even simpler is to just put the check in __init__, so to prevent the
caller from creating an instance of the class:
class AbstractStream(object):
def __init__(self):
if self.__class__ is Stream:
raise NotImplementedError('abstract class')
def resetStats(self):
# This does not need to be over-ridden.
_log.info('Reset statistics of %s' % self)
def whatever(self):
# This *must* be over-ridden, and *cannot* be called
raise NotImplementedError('abstract method')
If you have a lot of methods, you can probably reduce the boilerplate
with decorators:
# Untested
from functools import wraps
def abstract(func):
# Abstract methods don't have to be over-ridden, so long as they
# are called from a subclass of the abstract class.
@functools.wraps(func)
def inner(self, *args, **kwargs):
if self.__class__ is Stream:
raise NotImplementedError()
return func(self, *args, **kwargs)
return inner
def virtual(func):
# Virtual methods must be over-ridden, and must not be called by
# inheritance.
@functools.wraps(func)
def inner(self, *args, **kwargs):
raise NotImplementedError()
return inner
class Stream(object):
@abstract
def __init__(self):
pass
def resetStats(self):
_log.info('Reset statistics of %s' % self)
@virtual
def whatever(self):
pass
--
Steven
Sorry guys (means guys *and* gals :op ), 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
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
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
> Sorry guys (means guys *and* gals :op ), 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
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
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'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
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
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
Please don't call it an interface when it's really an abstract base
class. And abstract base classes are probably the solution the OP is
looking for, http://docs.python.org/library/abc.html
Christian
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
Scott....@Acm.Org
JM
Why are you trying to reinvent the wheel? Python's abc module already
takes care of these details.
Christian
JM
JM
> 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.
That's something I'd rather do in a custom metaclass. But YMMV, of course...