【发布时间】:2011-11-28 02:19:06
【问题描述】:
如何在 Python 中检查一个对象是否支持 [] 操作?我想到了类似的东西:
if supports(obj, ?[]?):
print("Supports")
【问题讨论】:
标签: python
如何在 Python 中检查一个对象是否支持 [] 操作?我想到了类似的东西:
if supports(obj, ?[]?):
print("Supports")
【问题讨论】:
标签: python
您不会“检查支持”。您只需使用它:
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 原则是,请求许可更容易请求宽恕。
该语言旨在执行此操作,但有例外。
【讨论】:
AttributeError 绝对是您可以在这里找到的东西,而不是 TypeError。
__getitem__ 的否定案例还要快!我真的必须重新考虑如何在 Python 中使用异常......
试试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].
返回索引 b 处 a 的值:
operator.getitem(a, b) operator.__getitem__(a, b)将a的切片从索引b返回到索引c-1:
operator.getslice(a, b, c) operator.__getslice__(a, b, c)将索引 b 处的 a 的值设置为 c:
operator.setitem(a, b, c) operator.__setitem__(a, b, c)将a的切片从索引b到索引c-1设置为序列v。
operator.setslice(a, b, c, v) operator.__setslice__(a, b, c, v)删除索引 b 处 a 的值:
operator.delitem(a, b) operator.__delitem__(a, b)从索引b到索引c-1删除a的切片:
operator.delslice(a, b, c) operator.__delslice__(a, b, c)
等等。
【讨论】:
[] 运算符的内部名称是 __getitem__(和 __setitem__),因此您可以通过以下方式进行很好的尝试:
if hasattr(obj, '__getitem__'):
print "Supports"
【讨论】:
tuple 不支持 __setitem__ 或 __delitem__。
根据language docs,您可以检查该类是否具有__getitem__ 方法。
【讨论】:
有一种简单的方法可以查看您是否可以迭代对象(即,执行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 而不是这种方法的唯一原因是,在你的for 周围有一个try 循环,谁知道还有什么,可能会有点复杂。
【讨论】:
[] 运算符与对象是否可迭代没有任何关系。您正在寻找collections.Sequence,这相当于检查__getitem__。
in”,因为这是您第一次学习 Python 中迭代的方式,for item in obj:,不是关于[],但我可以看看你是否还在用 C 语法思考这有什么意义。