开发者

Check for [] operator

How do I check whether an object supports [] operation in Python? I think of something like the following:

if supports(obj, ?[]?开发者_运维百科):
    print("Supports")  


You don't "check for support". You just use it:

try:
    a = obj[whatever]
except TypeError:
    # whatever your fall-back plan is when obj doesn't support [] (__getitem__) 

Writing your own isinstance is always the wrong thing to do. A new type that doesn't inherit from the collections ABC classes can still have the right behavior. Duck Typing means you can never rely on isinstance.

Writing your own hasattr test merely duplicates Python's internal checking that raises the exception. Since Python must do the test, why duplicate that?

Finally, "I think that with exception handling this code will be less readable." Is false. The Pythonic principle, accepted by many experienced Python programmers is that it's Easier to Ask Forgiveness That to Ask For Permission.

The language is designed to do this with exceptions.


Try hasattr(obj, "__getitem__"):

if hasattr(obj, "__getitem__"):
    print("Supports") 

From the operator.getitem help:

operator.getitem??
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function getitem>
Namespace:      Interactive
getitem(a, b) -- Same as a[b].

Check out the operator module:

  • Return the value of a at index b:

    operator.getitem(a, b)
    operator.__getitem__(a, b)
    
  • Return the slice of a from index b to index c-1:

    operator.getslice(a, b, c)
    operator.__getslice__(a, b, c)
    
  • Set the value of a at index b to c:

    operator.setitem(a, b, c)
    operator.__setitem__(a, b, c)
    
  • Set the slice of a from index b to index c-1 to the sequence v.

    operator.setslice(a, b, c, v)
    operator.__setslice__(a, b, c, v)
    
  • Remove the value of a at index b:

    operator.delitem(a, b)
    operator.__delitem__(a, b)
    
  • Delete the slice of a from index b to index c-1:

    operator.delslice(a, b, c)
    operator.__delslice__(a, b, c)
    

etc..


The internal name of the [] operator is __getitem__ (and __setitem__), so you can take a pretty good stab at this with:

if hasattr(obj, '__getitem__'):
    print "Supports"


You can check to see if the class has an __getitem__ method, as per the language docs.


There's an easy way to see if you can iterate over an object (ie, do a for i in obj):

import collections
if isinstance(obj, collections.Iterable):
    print 'obj supports iteration'

If you're concerned about checking if you can use an actual key, I'd recommend just "asking for forgiveness" rather than permission:

try:
    value = obj[key]
except (AttributeError, TypeError, IndexError):
    # These are different things that can return in different situations
    value = None
    print 'I guess that key doesn\'t work'

The only reason I would suggest using collections.Iterable instead of this method is that having a try around your for loop around who knows what else, can get kind of complicated.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜