469,328 Members | 1,288 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,328 developers. It's quick & easy.

can i implement virtual functions in python ?

Hi,

I'm new to python, so excuse me if i'm asking something dumb.
Does python provide a mechanism to implement virtual functions?
Can you please give a code snippet also...:)
Thanx in advance
-Prabu.
Jul 18 '05 #1
15 18512
my friend python coder, tell me all function are virtual in python , so...

"Prabu" <pr****@hotmail.com> a écrit dans le message news:
e7**************************@posting.google.com...
Hi,

I'm new to python, so excuse me if i'm asking something dumb.
Does python provide a mechanism to implement virtual functions?
Can you please give a code snippet also...:)
Thanx in advance
-Prabu.

Jul 18 '05 #2
Prabu wrote:
Hi,

I'm new to python, so excuse me if i'm asking something dumb.
Does python provide a mechanism to implement virtual functions? [...]


What do you mean with "virtual function"?

If you mean virtual methods in the C++ sense, all methods are "virtual"
in Python.

-- Gerhard

Jul 18 '05 #3
JCM
Prabu <pr****@hotmail.com> wrote:
....
I'm new to python, so excuse me if i'm asking something dumb.
Does python provide a mechanism to implement virtual functions?


Others have given good responses, but I'll jump in anyway.

Virtual functions (using C++ terminology) are something limited to
statically-typed languages. A virtual function call will be resolved
dynamically, based on the runtime type of the object. A non-virtual
call will be resolved at compile-time, based on the declared type of
the object. Since Python is dynamically typed, the only possibility
is for all methods to be "virtual".
Jul 18 '05 #4
Hello Prabu,
I'm new to python, so excuse me if i'm asking something dumb.
Does python provide a mechanism to implement virtual functions?
Can you please give a code snippet also...:)


http://www.python.org/doc/current/tu...00000000000000

Miki
Jul 18 '05 #5
I think you can do something like this.

class Virtual:
def myFunc(self, x):
pass

class Implement(Virtual):
def myFunc(self, x):
return x * x
Jul 18 '05 #6
pr****@hotmail.com (Prabu) wrote in message news:<e7**************************@posting.google. com>...
Hi,

I'm new to python, so excuse me if i'm asking something dumb.
Does python provide a mechanism to implement virtual functions?
Can you please give a code snippet also...:)
Thanx in advance
-Prabu.


As others have mentioned, all methods are overridable in python. But
if you want to create a genuine Abstract Base Class, raise
NotImplementedErrors for the virual methods. People will tell you
that this is not 'pythonic' (you should be using hasattr() to test for
interfaces) but I still find it useful from time to time.

PythonWin 2.3.2c1 (#48, Sep 30 2003, 09:28:31) [MSC v.1200 32 bit
(Intel)] on win32.
Portions Copyright 1994-2001 Mark Hammond (mh******@skippinet.com.au)
- see 'Help/About PythonWin' for further copyright information.
class virtualClass: .... def __init__(self):
.... pass
.... def virtualMethod1(self):
.... raise NotImplementedError("virtualMethod1 is virutal and
must be overridden.")
.... def concreteMethod1(self):
.... print "The concrete method is implemented"
....
x = virtualClass() x.concreteMethod1() The concrete method is implemented
x.virtualMethod1() Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", line 5, in virtualMethod1
NotImplementedError: virtualMethod1 is virutal and must be overridden.
class subClass(virtualClass): .... def virtualMethod1(self):
.... print "sub class implemented virtualMethod1"
....
y = subClass() y.concreteMethod1() The concrete method is implemented
y.virtualMethod1() sub class implemented virtualMethod1

Jul 18 '05 #7
logistix at cathoderaymission.net:
if you want to create a genuine Abstract Base Class, raise
NotImplementedErrors for the virual methods. People will tell you
that this is not 'pythonic' (you should be using hasattr() to test for
interfaces) but I still find it useful from time to time.


Really? I find hasattr to be non-Pythonic. Just get the object, like

try:
method = obj.function_name
except AttributeError:
... not implemented ...

However, I do use NotImplementedError so the exception
which percolates up is more obvious than AttributeError. It also
allows me to put in a docstring describing the interface requirements
of derived classes.

I also don't like the double attribute lookup in

if not hasattr(obj, "function_name"):
... not implemented ...
else:
obj.function_name(...)

but that's more a personal issue than Pythonic vs. non-Pythonic.

Andrew
da***@dalkescientific.com

Jul 18 '05 #8
Andrew Dalke wrote:

I also don't like the double attribute lookup in

if not hasattr(obj, "function_name"):
... not implemented ...
else:
obj.function_name(...)


Have you considered using getattr() with a default?

class Test:
def there(self):
print "there"

def default():
print "default"

t = Test()
for name in "there notThere".split():
getattr(t, name, default)()
Peter
Jul 18 '05 #9
Peter Otten:
Have you considered using getattr() with a default?


Yes, I have. It isn't always the right solution, unless
you do a bit of trickery.

Consider

class Test:
def there(self):
return DBConnect("example.com", "user", "passwd")

class TestNotThere:
pass

if random.choice([0, 1]) == 1:
x = Test()
else:
x = TestNotThere()

if hasattr(x, "there"):
conn = x.there()
conn.query("this where that is the other").dump()
print "There you go", conn.username
conn.shutdown()

You can't replace the hasattr(x, "there") with a
getattr(x, "there", default_function) because even if
the default function returned an object which implements
'query', 'shutdown' and 'user' correctly, the output will
contain the text "There you go", which shouldn't happen.

A better option getattr solution is to compare the
returned object against the default

f = getattr(x, "there", None)
if f is not None:
conn = f()
...

(Note that you must use 'is' here and not == because
the latter can trigger arbitrary Python code, which has
a different behaviour than the hasattr approach.)

However, suppose TestNotThere.there is not a method
but is the None object. The original hasattr code raises
a 'TypeError - not callable' exception but this getattr
version won't, which means the API is different and
allows errors to slip silently by.

The better solution is to create an object which you
can guarantee is not present anywhere else. For
example, you could do

class _default: pass # guaranteed to be unique

f = getattr(x, "there", _default)
if f is not _default:
conn = f()
...

I don't consider that code all that clean. It isn't obvious
why the _default class is needed. Compare that to my
prefered code

try:
f = x.there
except AttributeError:
pass
else:
conn = f()

This code is longer, and I admit it isn't the clearest (I
would prefer the exception case be after the else case).
It's also slower because of the exception creation, unless
exceptions are rare. But it exactly equivalent to the
hasattr test except without the double attribute lookup,
and it uses a standard construct instead of depending
on a class creation to make an object which is guaranteed
to be unique.

In any case, remember that I said it's a personal preference,

Plus, most of the time a getattr with a default value is
the right solution. It's just not a general panacea.

Andrew
da***@dalkescientific.com
Jul 18 '05 #10
Andrew Dalke wrote:
...
The better solution is to create an object which you
can guarantee is not present anywhere else. For
example, you could do

class _default: pass # guaranteed to be unique

f = getattr(x, "there", _default)
if f is not _default:
conn = f()
...

I don't consider that code all that clean. It isn't obvious
why the _default class is needed. Compare that to my
I think the "guaranteed to be unique" comment SHOULD make it
pretty obvious (to Pythonistas advanced enough to grasp the
try/except/else construct that we both prefer).
and it uses a standard construct instead of depending
on a class creation to make an object which is guaranteed
to be unique.
Actually if you object to the "class creation" (which IS also
a standard construct:-), use ANY mutable object instead, e.g.:

_default = [] # ANY arbitrary mutable object, just for uniqueness
f = getattr(x, 'there', _default)
# etc etc

In any case, remember that I said it's a personal preference,


Yeah, that's probably what's rubbing on people's nerves -- there
is SUPPOSED TO BE "ideally only one obvious way". Maybe it
would help if we were Dutch;-).
Alex

Jul 18 '05 #11
On 30 Sep 2003 07:53:07 -0700, pr****@hotmail.com (Prabu) wrote:
Hi,

I'm new to python, so excuse me if i'm asking something dumb.
Does python provide a mechanism to implement virtual functions?
Can you please give a code snippet also...:)
Thanx in advance
-Prabu.


As others have said, in Python all methods are effectively virtual.

Late (or dynamic) binding is the object-oriented ideal, and that is
what virtual methods give you in C++.

In C++, dynamic binding requires a 'virtual table' to provide the link
from an instance object to the appropriate implementation of a virtual
method. The instance object contains a pointer to the virtual table,
which in turn contains effectively a function pointer for each virtual
method.

This is done purely so that the caller need not know exactly what
class it is calling and yet the correct implementation of the method
will be invoked. The decision of exactly what implementation of that
function to call is made at runtime (ie late) rather than at compile
time.

The trouble is that this virtual-table lookup is sometimes considered
slow. A statically bound (or early bound) method is a little faster
because the decision of what implementation to call has been made by
the compiler at each point where the method is called. Virtual table
lookup isn't needed.

Basically, a C++ virtual method call is implemented something like the
following...

(instance_obj->vtable [method_id]) (instance_obj, other_args);

Whereas a C++ non-virtual method call is simply...

method_fn (instance_obj, other_args);

(this is, I think, only the single inheritance case - things may be a
bit more complex for multiple inheritance)

Python is a much more dynamic language than terms such as 'early
binding' would imply. Each call has a lookup by name at the time it is
called. This certainly supports dynamic binding, but goes further -
you can pass any instance object that provides the required set of
methods to a function and that function will just work.

If your reason for using a base class to your subclasses is simply so
that the same functions/classes can call shared methods in the
subclasses, this is unnecessary and provides few benefits in Python.
Python classes tend to share a 'protocol' rather than an explicit
interface. At least 90% of the time, inheritance in Python is just a
shorthand for creating a class which implements the same protocol (and
a way of making the relationship more explicit in the source code, of
course). Actually checking the type of an instance object is quite
rare in my experience.
--
Steve Horne

steve at ninereeds dot fsnet dot co dot uk
Jul 18 '05 #12
"Andrew Dalke" <ad****@mindspring.com> wrote in message news:<jt******************@newsread3.news.pas.eart hlink.net>...
logistix at cathoderaymission.net:
if you want to create a genuine Abstract Base Class, raise
NotImplementedErrors for the virual methods. People will tell you
that this is not 'pythonic' (you should be using hasattr() to test for
interfaces) but I still find it useful from time to time.


Really? I find hasattr to be non-Pythonic. Just get the object, like

try:
method = obj.function_name
except AttributeError:
... not implemented ...

However, I do use NotImplementedError so the exception
which percolates up is more obvious than AttributeError. It also
allows me to put in a docstring describing the interface requirements
of derived classes.

I also don't like the double attribute lookup in

if not hasattr(obj, "function_name"):
... not implemented ...
else:
obj.function_name(...)

but that's more a personal issue than Pythonic vs. non-Pythonic.


Yes, try...except is equally valid, but I'm still brainwashed to
believe that exceptions are bad and should be avoided if possible. I
still cringe when I write code that throws a 'StopIteration'
exception. Like you say, its a personal issue, and I'll bring it up
with my therapist.

The point I was trying to make is that the least pythonic way to test
is use inheritance based interfaces and issubclass() or isinstance().
I've got yelled at every time I've posted code here that does it.

Still, once you get beyond trivial examples and you're writing special
purpose code I find it handy. For example, what's the best way to
test for an interface in this code?

def foo(x):
x.a()
x.b()
x.c()

Either using hasattr or or a try...except clause gets a little clunky.
I'd just rather do something like:

class abstract:
def a(self): raise NotImplementedError("Virtual Method")
def b(self): raise NotImplementedError("Virtual Method")
def c(self): raise NotImplementedError("Virtual Method")

class implementation(abstract):
def a(self): print "a"
def b(self): print "b"
def c(self): print "c"

def foo(x):
assert isinstance(x, abstract), "foo expects an 'abstract'
interface"
x.a()
x.b()
x.c()

Or I suppose I could just let the interpreter throw an exception for
me when it can't find any of the appropriate methods. ;)
Jul 18 '05 #13
Alex:
I think the "guaranteed to be unique" comment SHOULD make it
pretty obvious (to Pythonistas advanced enough to grasp the
try/except/else construct that we both prefer).
True. I don't like making the comment since it feels like I'm
using a side effect of the implementation.
Actually if you object to the "class creation" (which IS also
a standard construct:-), use ANY mutable object instead, e.g.:


Ahh, of course. Is that guaranteed in the language spec?
For example, suppose I had

x = []
y = []
assert x is not y

Could a future Python implementation support copy-on-write
and return a reference to the same empty list, but which
becomes a different list on mutation?

Here's what the docs say:
] Every object has an identity, a type and a value. An object's
] identity never changes once it has been created; you may
] think of it as the object's address in memory. The `is' operator
] compares the identity of two objects; the id() function returns
] an integer representing its identity (currently implemented as its
] address).

In order for my conjecture to occur, x and y would have to
have the same id, as that's what the 'is' test uses. But since
since the id is fixed over the lifetime of an object, copy-on-write
won't change it, so all lists which start as [] would have the
same id. Since I'm supposed to think of the id as a position
in memory, I have to assume that two objects with the same
id are the same object, so no, a future implementation cannot
make this change.
In any case, remember that I said it's a personal preference,


Yeah, that's probably what's rubbing on people's nerves -- there
is SUPPOSED TO BE "ideally only one obvious way". Maybe it
would help if we were Dutch;-).


I'm 1/4th Dutch; is that my problem? :)

No, you're right. I'm a proponent of the "preferably only one
obvious way to do it" guideline. Why do I consider this a personal
preference?

When I use default arguments and need to distinguish between
a 1 argument and a 2 argument call (which is rare), I'll use

class _undefined: pass

def function(a, b = _undefined):
if b is _undefined:
...

In addition, if I need to do several test for exists/doesn't exist
(also rare) then I'll do

class _undefined: pass

x = getattr(obj, "blah", _undefined)
if x is _undefined:
...
y = getattr(obj, "blarg", _undefined)
if y is _undefeind:
...

because it's more concise than the try/except/else approach.

Interesting. I looks like my internal guideline is to use
t/e/e iff the test is needed once and if a _undefined object
is not defined in the module, else use an _undefined.

That seems inelegant. If there's a prefered style for this
then it seems it should be the use of an _undefined object
and not t/e/e.

Comments?

Andrew
da***@dalkescientific.om
Jul 18 '05 #14
Me:
However, I do use NotImplementedError so the exception
which percolates up is more obvious than AttributeError. It also
allows me to put in a docstring describing the interface requirements
of derived classes.

logistix at cathoderaymission.net: Either using hasattr or or a try...except clause gets a little clunky.
I'd just rather do something like:

class abstract:
def a(self): raise NotImplementedError("Virtual Method")
def b(self): raise NotImplementedError("Virtual Method")
def c(self): raise NotImplementedError("Virtual Method")


Well, I agreed with you ;)

I think this is the right way, and it lets you include a
docstring to describe the interface better.

Andrew
da***@dalkescientific.com
Jul 18 '05 #15
"Andrew Dalke" <ad****@mindspring.com> wrote in message news:<dP******************@newsread3.news.pas.eart hlink.net>...
Me:
However, I do use NotImplementedError so the exception
which percolates up is more obvious than AttributeError. It also
allows me to put in a docstring describing the interface requirements
of derived classes.


logistix at cathoderaymission.net:
Either using hasattr or or a try...except clause gets a little clunky.
I'd just rather do something like:

class abstract:
def a(self): raise NotImplementedError("Virtual Method")
def b(self): raise NotImplementedError("Virtual Method")
def c(self): raise NotImplementedError("Virtual Method")


Well, I agreed with you ;)

DOH! You did agree with me ;) Sorry about that. I thought you were
talking about re-raising an AttributeError as a NotImplementedError in
the except clause.
Jul 18 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by The Stevemeister | last post: by
20 posts views Thread by Nemanja Trifunovic | last post: by
17 posts views Thread by Riaan | last post: by
2 posts views Thread by david.sanderson | last post: by
7 posts views Thread by v4vijayakumar | last post: by
6 posts views Thread by Pallav singh | last post: by
6 posts views Thread by Vijay Meena | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.