Python "implements <interface>" equivalent?
Bruno Desthuilliers
bdesth.quelquechose at free.quelquepart.fr
Wed Oct 3 08:05:52 EDT 2007
Grant Edwards a écrit :
> On 2007-10-04, Bruno Desthuilliers <bruno.42.desthuilliers at wtf.websiteburo.oops.com> wrote:
>
>
>>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
More information about the Python-list
mailing list