Pure virtual functions in Python?

L

lallous

Hello

How can I do something similar to pure virtual functions in C++ ?

Let us consider this:

class C1:

# Pure virtual
def cb(self, param1, param2):
"""
This is a callback

@param param1: ...
@param param2: ...
"""
raise NotImplementedError, "Implement me"

# Implementation w/o a 'cb', thus 'cb' should not be used
class C2(C1):
def __init__(self):
pass

# Implementation w/ 'cb', thus 'cb' can be used
class C3(C1):
def __init__(self):
pass

def cb(self, param1, param2):
print "i am c3 cb"

# Dispatcher function that calls 'cb' only if 'cb' is implemented in
child classes
def dispatcher(c):
if hasattr(c, 'cb'):
c.cb("Hello", "World")

dispatcher(C2())
dispatcher(C3())

What I want is the ability to have the dispatcher() not to call 'cb'
if it was not implemented in one of the child classes.

Please advise.
 
D

Diez B. Roggisch

Am 20.02.10 17:12, schrieb lallous:
Hello

How can I do something similar to pure virtual functions in C++ ?

Let us consider this:

class C1:

# Pure virtual
def cb(self, param1, param2):
"""
This is a callback

@param param1: ...
@param param2: ...
"""
raise NotImplementedError, "Implement me"

# Implementation w/o a 'cb', thus 'cb' should not be used
class C2(C1):
def __init__(self):
pass

# Implementation w/ 'cb', thus 'cb' can be used
class C3(C1):
def __init__(self):
pass

def cb(self, param1, param2):
print "i am c3 cb"

# Dispatcher function that calls 'cb' only if 'cb' is implemented in
child classes
def dispatcher(c):
if hasattr(c, 'cb'):
c.cb("Hello", "World")

dispatcher(C2())
dispatcher(C3())

What I want is the ability to have the dispatcher() not to call 'cb'
if it was not implemented in one of the child classes.

Please advise.

There is nothing more beyond that what you already did. You can raise a
NotImplementedError for classes that don't implement the method. That's it.

Diez
 
M

Martin v. Loewis

class C1:
There is nothing more beyond that what you already did. You can raise a
NotImplementedError for classes that don't implement the method. That's it.

That's not true. Currently, the hasattr() call would report that cb is
available, when it is actually not implemented. It would be possible to
do something like

if hasattr(c, 'cb') and not is_pure(c.cb):
c.cb("Hello", "World")

is_pure could, for example, look at a function attribute of the
callback. You'd write something like

@pure_virtual
def cb(self, param1, param2):
not_implemented

Regards,
Martin
 
D

Diez B. Roggisch

Sorry, I totally mis-read the OP, too tired. You are right of course.

Diez
 
R

Rami Chowdhury

Am 20.02.10 17:12, schrieb lallous:

There is nothing more beyond that what you already did. You can raise a
NotImplementedError for classes that don't implement the method. That's it.

Diez

Perhaps you could use an easier-to-ask-forgiveness-than-permission idiom?

def dispatcher(c):
try:
c.cb("Hello", "World")
except NotImplementedError:
pass
 
A

Arnaud Delobelle

lallous said:
Hello

How can I do something similar to pure virtual functions in C++ ?

Let us consider this:

class C1:

# Pure virtual
def cb(self, param1, param2):
"""
This is a callback

@param param1: ...
@param param2: ...
"""
raise NotImplementedError, "Implement me"

Why define it if it is virtual?
# Implementation w/o a 'cb', thus 'cb' should not be used
class C2(C1):
def __init__(self):
pass

# Implementation w/ 'cb', thus 'cb' can be used
class C3(C1):
def __init__(self):
pass

def cb(self, param1, param2):
print "i am c3 cb"

# Dispatcher function that calls 'cb' only if 'cb' is implemented in
child classes
def dispatcher(c):
if hasattr(c, 'cb'):
c.cb("Hello", "World")

dispatcher(C2())
dispatcher(C3())

What I want is the ability to have the dispatcher() not to call 'cb'
if it was not implemented in one of the child classes.

If you don't define cb in the parent class, it'll work.
 
L

lallous

That's not true. Currently, the hasattr() call would report that cb is
available, when it is actually not implemented. It would be possible to
do something like

  if hasattr(c, 'cb') and not is_pure(c.cb):
      c.cb("Hello", "World")

is_pure could, for example, look at a function attribute of the
callback. You'd write something like

  @pure_virtual
  def cb(self, param1, param2):
      not_implemented

Regards,
Martin

Hello Martine,

Can you elaborate more on how to use the mechanism you described?

Thanks,
Elias
 
L

lallous

Thanks everyone for the answers.

The dispatcher() is actually sits in C++ code.

So my code receives an object that is an instance of the base class,
it PyObject_GetAttrString(py_obj, 'funcname'). If the attribute exists
I will call PyObject_CallMethod on it.

If the base defines the method and it was empty, then my C++ code
would still call the function. This is not optimal because I don't
want to go from C++ to Python if the _derived_ class does not
implement the cb. Now the base class should define it so that doc
parsers properly describe the base class.

The recipe suggested is not worth the trouble.
Unfortunately I cannot use abc module since I use Python 2.5
 
M

Martin v. Loewis

That's not true. Currently, the hasattr() call would report that cb is
Hello Martine,

Can you elaborate more on how to use the mechanism you described?

There are various ways to do it; the one I had in mind uses function
attributes:

def pure_virtual(func):
func.pure_virtual = True # only presence of attribute matters,
# not value
return func

def is_pure(method): # method might be either a method or a function
try:
func = method.im_func
except AttributeError:
func = method
return hasattr(func, 'pure_virtual')

not_implemented = object() # could also write pass instead, or raise

HTH,
Martin
 
L

Lie Ryan

On 02/21/10 19:27, lallous wrote:
If the base defines the method and it was empty, then my C++ code
would still call the function. This is not optimal because I don't
want to go from C++ to Python if the _derived_ class does not
implement the cb.

That sounds like a microoptimization; have you profiled your code and
determined that calling empty function causes a bottleneck? I doubt it.
Now the base class should define it so that doc
parsers properly describe the base class.
The recipe suggested is not worth the trouble.
Unfortunately I cannot use abc module since I use Python 2.5

Because nobody here could have guessed that your dispatcher was written
in C++; your problem is near trivial if your dispatcher is a pure-python
code.
 
G

Gregory Ewing

lallous said:
If the base defines the method and it was empty, then my C++ code
would still call the function. This is not optimal because I don't
want to go from C++ to Python if the _derived_ class does not
implement the cb.

I would simply not implement the method at all in the base
class. Then the C++ code can do an attribute lookup for
the method, and if it's not found, do nothing.
 
J

Jean-Michel Pichavant

Arnaud said:
Why define it if it is virtual?

Slightly off topic but this is often useful when writing interfaces. You
can then properly document what should any subclass (interface
implemention) be doing.
The thing is that in case of virtual methods, you *do want* to raise the
notImplemented exceptions, meaning you've failed to implement all the
required methods.
Strange thing that the OP want to silently call nothing at all when
calling a virtual method, he looses all the benefits from a virtual design.
Anyway, I don't deal into code optimization, this is not healthy :)

JM
 
L

lallous

On 02/21/10 19:27,lallouswrote:


That sounds like a microoptimization; have you profiled your code and
determined that calling empty function causes a bottleneck? I doubt it.


Because nobody here could have guessed that your dispatcher was written
in C++; your problem is near trivial if your dispatcher is a pure-python
code.

You are right. I haven't checked how much it costs to continuously
call an empty function, but why do it if I know (during initialization
from my C++ dispatcher code) that certain Python object should not
have certain methods called.

I still prefer not to call at all, even if it was an empty function.

Regards,
Elias
 
L

lallous

lallouswrote:

I would simply not implement the method at all in the base
class. Then the C++ code can do an attribute lookup for
the method, and if it's not found, do nothing.


That is what I currently do. But if I comment out the implementations
(empty ones) then the documentation generation tool will not document
the callbacks.
 
J

Jean-Michel Pichavant

lallous said:
I still prefer not to call at all, even if it was an empty function.

Regards,
Elias

Is there any way we could convince you that there is no point caring
about this ? Even if you were trying to optimize speed, it would still
require proof that an empty function is part of the problem.
It sounds like someone stating "I prefer to write difficult-to-read
code, because in 1978, code size used to matter".

JM
 
A

Aahz

That is what I currently do. But if I comment out the implementations
(empty ones) then the documentation generation tool will not document
the callbacks.

Maybe deleting the method after the class would work.
--
Aahz ([email protected]) <*> http://www.pythoncraft.com/

"Many customs in this life persist because they ease friction and promote
productivity as a result of universal agreement, and whether they are
precisely the optimal choices is much less important." --Henry Spencer
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top