Python "implements <interface>" equivalent?

  • Thread starter Bruno Desthuilliers
  • Start date
B

Bruno Desthuilliers

Grant Edwards a écrit :
Yes, and it's even simpler : just pass your object. If it effectively
implements the desired interface, everything will work fine !-)
[...]

What I'd like to do is create a feature detection system for
my work -- specifically, a general class / interface called
"Feature" and then subclasses that implement functions like
isFeaturePresent() in all of their different and unique ways.
I'd love to hear how I can do this in Python.

I'm not sure about what you exactly want to do, but FWIW, checking if an
object has a given attribute is quite simple:

if has_attr(obj, 'attribute_name'):
print "Hurray"
else:
print "D'oh"

Note that in Python, methods are attributes too - only they
are callable.


On a slight tangent....

The "Pythonic" way to handle things like that is often just
to call the method you want to call. If the object doesn't
have that method, then you catch the exception and do whatever
it is you do in the case where the object doesn't have the
feature in question.

Depends... If you expect the object to have this attribute most of the
time, then the try/except solution is fine, but else it might be better
to look-before-you-leap - try/except blocks are costly when there's
effectively an exception.

As a side note, you may not necessarily want to actually call the
method, only know if it's there. As a side-side note, if you want to
call it but choose the look-before-you-leap approach, using getattr()
and storing a local reference to the method might be better, since it
avoids a second lookup.
The tricky bit is only catching the AttributeError exception
generated by the attempt to access the non-existant method, and
not catching AttributeError exceptions generated by bugs in the
method when it does exist.

Once you've added code to make sure you only catch exceptions
you care about, it's simpler to just call has_attr

the obvious method

try:
myobj.feature1()
except AttributeError:
print "object doesn't implement feature1"

isn't correct, since an unhandled AttributeError generated by
the feature1 method will print "object doesn't implement
feature1".

Indeed. In this case, it would be better to *not* catch the exception.
At least, the traceback will make clear where the AttributeError comes from.
Attempting to isolate the attributeError we care
about looks like this:

try:
m = myobj.feature1
except AttributeError:
print "object doesn't implement feature1"
else:
m()

Which might raise a TypeError if myobj.feature1 is not callable !-)
That's just too messy compared with the has_attr method that
goes like this:

if has_attr(myobj,'feature1'):
myobj.feature1()
else:
print "object doesn't implement feature1"

However, I don't like that alot because you've got to supply
the method name twice: once as a string and once as the method
name.

What's the cleanest way to call a method that might not be
there?

m = getattr(myobj, 'feature1', None)
if callable(m):
m()
else:
print "%s doesn't implement feature1()" % myobj
 
B

Bruno Desthuilliers

Lawrence D'Oliveiro a écrit :
In message <[email protected]>, Wojciech
Gryc wrote:




Why?

Interfaces are just a euphemism for multiple inheritance,

Java's 'interface' mechanism is mostly a (somewhat weak & dumb IMHO)
mean to decouple (sub)typing from implementation. Given a declarative
static type system and the restriction to single implementation
inheritance, of course. IIRC, vb6 had *no* implementation inheritance at
all - you had to do 'implement' it by yourself, using (manual of course)
delegation...

Now multiple inheritence is clearly not the answer to the OP's question
in a dynamically typed language, where subtyping is not bound to
inheritance.
 
W

Wojciech Gryc

Hi,

I recently started using Python and am extremely happy with how
productive it's made me, even as a new user. I'm hoping to continue
using the language for my research, and have come across a bit of a
stumbling block.

I'm a seasoned Java programmer and quite a big fan of interfaces...
i.e. The idea that if I make a number of distinct classes that
implement interface X, I can pass them all as parameters to functions
or whatnot that require an X object.

Is there something similar in Python?

What I'd like to do is create a feature detection system for my work
-- specifically, a general class / interface called "Feature" and then
subclasses that implement functions like isFeaturePresent() in all of
their different and unique ways. I'd love to hear how I can do this in
Python.

Thanks,
Wojciech
 
J

Jarek Zgoda

Wojciech Gryc napisa³(a):
I'm a seasoned Java programmer and quite a big fan of interfaces...
i.e. The idea that if I make a number of distinct classes that
implement interface X, I can pass them all as parameters to functions
or whatnot that require an X object.

Is there something similar in Python?

The closest thing I saw is zope.interface.
What I'd like to do is create a feature detection system for my work
-- specifically, a general class / interface called "Feature" and then
subclasses that implement functions like isFeaturePresent() in all of
their different and unique ways. I'd love to hear how I can do this in
Python.

I am sure you wouldn't need interfaces to do such things in Python.
"Duck typing" is how we call this feature. :)
 
C

Carl Banks

Hi,

I recently started using Python and am extremely happy with how
productive it's made me, even as a new user. I'm hoping to continue
using the language for my research, and have come across a bit of a
stumbling block.

I'm a seasoned Java programmer and quite a big fan of interfaces...
i.e. The idea that if I make a number of distinct classes that
implement interface X, I can pass them all as parameters to functions
or whatnot that require an X object.

Is there something similar in Python?


Yes: you do it pretty much the same way you'd do it in Java, except
for two differences:
* leave out the "implements Interface" part
* don't actually create an Interface class

And then, voila!, you can write functions that can accept any class
that implements your interface.

What I'd like to do is create a feature detection system for my work
-- specifically, a general class / interface called "Feature" and then
subclasses that implement functions like isFeaturePresent() in all of
their different and unique ways. I'd love to hear how I can do this in
Python.

Just define isFeaturePresent() in any class you want. That's all you
have to do; any class that defines this method can be passed to any
function that invokes it, without having to "implement" or "subclass"
anything.

This is known as "duck typing" in Python lingo.


Carl Banks
 
W

Wojciech Gryc

Thank you Carl and thank you Jarek. This makes me feel much better --
on to coding, I shall go. :)

Thanks again,
Wojciech
 
B

Bruno Desthuilliers

Wojciech Gryc a écrit :
Hi,

I recently started using Python and am extremely happy with how
productive it's made me, even as a new user. I'm hoping to continue
using the language for my research, and have come across a bit of a
stumbling block.

I'm a seasoned Java programmer

So you may want to read this:

http://dirtsimple.org/2004/12/python-is-not-java.html

http://dirtsimple.org/2004/12/java-is-not-python-either.html
and quite a big fan of interfaces...
i.e. The idea that if I make a number of distinct classes that
implement interface X, I can pass them all as parameters to functions
or whatnot that require an X object.

Is there something similar in Python?

Yes, and it's even simpler : just pass your object. If it effectively
implements the desired interface, everything will work fine !-)

IOW : Python is dynamically typed, there's no parameters type
declaration and no parameters type checking at compile time - so you
just don't need to tell the compiler that your class implements a given
interface. Anyway, this would be a waste of time since you can
add/delete/replace attributes and methods at runtime either on a
per-class or per-instance basis.
What I'd like to do is create a feature detection system for my work
-- specifically, a general class / interface called "Feature" and then
subclasses that implement functions like isFeaturePresent() in all of
their different and unique ways. I'd love to hear how I can do this in
Python.

I'm not sure about what you exactly want to do, but FWIW, checking if an
object has a given attribute is quite simple:

if has_attr(obj, 'attribute_name'):
print "Hurray"
else:
print "D'oh"

Note that in Python, methods are attributes too - only they are callable.
 
G

Grant Edwards

Yes, and it's even simpler : just pass your object. If it effectively
implements the desired interface, everything will work fine !-) [...]
What I'd like to do is create a feature detection system for
my work -- specifically, a general class / interface called
"Feature" and then subclasses that implement functions like
isFeaturePresent() in all of their different and unique ways.
I'd love to hear how I can do this in Python.

I'm not sure about what you exactly want to do, but FWIW, checking if an
object has a given attribute is quite simple:

if has_attr(obj, 'attribute_name'):
print "Hurray"
else:
print "D'oh"

Note that in Python, methods are attributes too - only they
are callable.

On a slight tangent....

The "Pythonic" way to handle things like that is often just
to call the method you want to call. If the object doesn't
have that method, then you catch the exception and do whatever
it is you do in the case where the object doesn't have the
feature in question.

The tricky bit is only catching the AttributeError exception
generated by the attempt to access the non-existant method, and
not catching AttributeError exceptions generated by bugs in the
method when it does exist.

Once you've added code to make sure you only catch exceptions
you care about, it's simpler to just call has_attr

the obvious method

try:
myobj.feature1()
except AttributeError:
print "object doesn't implement feature1"

isn't correct, since an unhandled AttributeError generated by
the feature1 method will print "object doesn't implement
feature1". Attempting to isolate the attributeError we care
about looks like this:

try:
m = myobj.feature1
except AttributeError:
print "object doesn't implement feature1"
else:
m()

That's just too messy compared with the has_attr method that
goes like this:

if has_attr(myobj,'feature1'):
myobj.feature1()
else:
print "object doesn't implement feature1"

However, I don't like that alot because you've got to supply
the method name twice: once as a string and once as the method
name.

What's the cleanest way to call a method that might not be
there?
 
T

Terry Reedy

| Hi,
|
| I recently started using Python and am extremely happy with how
| productive it's made me, even as a new user. I'm hoping to continue
| using the language for my research, and have come across a bit of a
| stumbling block.
|
| I'm a seasoned Java programmer and quite a big fan of interfaces...
| i.e. The idea that if I make a number of distinct classes that
| implement interface X, I can pass them all as parameters to functions
| or whatnot that require an X object.
|
| Is there something similar in Python?

As others have noted, without typechecks, Python code is generic. For
example, 'a+b' means "Try a.__add__(b). If that does not work, try
b.__radd__(a). If that does not, raise an error."

| What I'd like to do is create a feature detection system for my work
| -- specifically, a general class / interface called "Feature" and then
| subclasses that implement functions like isFeaturePresent() in all of
| their different and unique ways. I'd love to hear how I can do this in
| Python.

If you have several methods (with multiple implementations), an abstract
base class can be helpful:

class Feature(object):
def isFeaturePresent(self):
raise NotImplementedError
def otherMethod(self):
raise NotImplementedError
# etc

Inherit from Feature (and possibly other classes -- Python has multiple
inheritance) to make your subclasses. Then put 'if not isinstance(arg,
Feature): raise TypeError(func requires Features)' at the top of functions
that work on Features. If you call Feature methods more than once in a
function, this save multiple checks or try-except blocks.

The cost, of course, is the inheritance requirement.

Terry Jan Reedy
 
L

Lawrence D'Oliveiro

I'm a seasoned Java programmer and quite a big fan of interfaces...
i.e. The idea that if I make a number of distinct classes that
implement interface X, I can pass them all as parameters to functions
or whatnot that require an X object.

Why?

Interfaces are just a euphemism for multiple inheritance, except it's sort
of a crippled compromise to keep the single-inheritance fanatics from
getting too unhappy.
 
S

Sion Arrowsmith

Grant Edwards said:
try:
myobj.feature1()
except AttributeError:
print "object doesn't implement feature1"

isn't correct, since an unhandled AttributeError generated by
the feature1 method will print "object doesn't implement
feature1".

I'd be tempted to argue that it *was* correct, since the object
doesn't implement a feature1 which can be used. (This is the cue
for someone to talk about making sure that myobj's class has
been thoroughly unit tested.)
 
D

David

I'm a seasoned Java programmer and quite a big fan of interfaces...
i.e. The idea that if I make a number of distinct classes that
implement interface X, I can pass them all as parameters to functions
or whatnot that require an X object.

Is there something similar in Python?

Python will probably be getting Abstract Base Classes at some point.

http://www.python.org/dev/peps/pep-3119/

For ABC in current versions of Python, see the "Can you implement
abstract classes in Python in 0 lines of code? Or 4?" question on this
page: http://norvig.com/python-iaq.html

David.
 

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

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top