检查[]运算符

时间:2011-09-29 23:11:16

标签: python

如何在Python中检查对象是否支持[]操作?我想到类似以下内容:

if supports(obj, ?[]?):
    print("Supports")  

5 个答案:

答案 0 :(得分:14)

您没有“检查支持”。你只需使用它:

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

编写自己的isinstance总是错误的。不从集合ABC类继承的新类型仍然可以具有正确的行为。 Duck Typing意味着你永远不能依赖isinstance

编写自己的hasattr测试只会复制Python引发异常的内部检查。由于Python 必须进行测试,为什么要复制呢?

最后,“我认为通过异常处理,这段代码的可读性会降低。”是假的。许多经验丰富的Python程序员都接受的Pythonic原则是,要求宽恕更容易获得许可。

该语言旨在通过例外来实现此目的。

答案 1 :(得分:5)

尝试hasattr(obj, "__getitem__")

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

来自operator.getitem帮助:

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].

查看operator module

  
      
  • 返回索引b的值:

    operator.getitem(a, b)
    operator.__getitem__(a, b)
    
  •   
  • 将索引b的切片返回到索引c-1:

    operator.getslice(a, b, c)
    operator.__getslice__(a, b, c)
    
  •   
  • 将索引b的值设置为c:

    operator.setitem(a, b, c)
    operator.__setitem__(a, b, c)
    
  •   
  • 将索引b的切片设置为索引c-1到序列v。

    operator.setslice(a, b, c, v)
    operator.__setslice__(a, b, c, v)
    
  •   
  • 删除索引b的值:

    operator.delitem(a, b)
    operator.__delitem__(a, b)
    
  •   
  • 将索引b的切片删除为索引c-1:

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

等。

答案 2 :(得分:3)

[]运算符的内部名称为__getitem__(以及__setitem__),因此您可以通过以下方式进行相当好的尝试:

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

答案 3 :(得分:2)

根据language docs,您可以检查班级是否有__getitem__方法。

答案 4 :(得分:2)

有一种简单的方法可以查看是否可以迭代一个对象(即执行for i in obj):

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

如果您担心检查是否可以使用实际密钥,我建议只是“请求原谅”而不是许可:

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'

我建议使用collections.Iterable代替此方法的唯一原因是,围绕try循环的for知道还有什么,可能会变得复杂。