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)
> 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.
> 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)
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.
On Fri, 14 Aug 2009 16:49:47 +0200, 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.
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
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 :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.
> 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 :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.
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"
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 :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.
> 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"
> 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.
> 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.
On Fri, 14 Aug 2009 18:49:26 +0200, Jean-Michel Pichavant wrote: > 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.
>> 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
>>> 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.
>>> 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
> (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.
Steven D'Aprano wrote: > On Fri, 14 Aug 2009 18:49:26 +0200, Jean-Michel Pichavant wrote:
>> 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:
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.
>>>> 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
>> (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.
Jean-Michel Pichavant wrote: > 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
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
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 :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:
> 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 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 :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:
>> 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) > ...
Christian Heimes wrote: > Jean-Michel Pichavant wrote: >> 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
> 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
Sadly I'm working with python 2.4. Anyway it's good to hear they've added ABC support to python, didn't know that. I didn't know there was a difference between interface and abstract classes as well. With a little bit of googling, I found out that actually Interface classes do not provide any implementation. What I'm looking for is definitely an abstract class.
> Jean-Michel Pichavant wrote: >>> Scott.Dani...@Acm.Org >> That could do the trick, sparing me from writing additional code in >> each methods. Thanks.
> Why are you trying to reinvent the wheel? Python's abc module already > takes care of these details.
> Christian
I'm working with python 2.4 and don't plan to change. The abc module would have been exactly what I was looking for. I'll keep it mind if I ever upgrade to python 2.6+
> 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.
> 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...