Grant Edwards a écrit : > On 2007-10-04, Bruno Desthuilliers <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list