如果 Python 对象是“可下标的”,这意味着啥?
Posted
技术标签:
【中文标题】如果 Python 对象是“可下标的”,这意味着啥?【英文标题】:What does it mean if a Python object is "subscriptable" or not?如果 Python 对象是“可下标的”,这意味着什么? 【发布时间】:2010-09-18 00:49:25 【问题描述】:哪些类型的对象属于“可下标”的领域?
【问题讨论】:
【参考方案1】:基本上意味着对象实现了__getitem__()
方法。换句话说,它描述的是“容器”的对象,这意味着它们包含其他对象。这包括字符串、列表、元组和字典。
【讨论】:
可靠程度如何:hasattr(SomeClassWithoutGetItem, '__getitem__')
确定事物是否可下标?
[
...]
索引语法称为下标,因为它等同于使用实际下标的数学符号;例如a[1]
是数学家写成 a₁ 的 Python。所以“可下标”的意思是“可以下标”。这在 Python 术语中意味着它必须实现__getitem__()
,因为a[1]
只是a.__getitem__(1)
的语法糖。
对hasattr
的调用应该可以正常工作,但这不是Pythonic 的做事方式; Python 实践鼓励Duck Typing。这意味着,如果您打算尝试使用下标从对象中获取项目,请继续执行;如果您认为它可能无法工作,因为该对象不可下标,请将其包装在带有 except TypeError
的 try
块中。
super
似乎是个例外。 super
返回的对象可以有__getitem__
的属性,但不能下标,因此括号切片不起作用。【参考方案2】:
下标在计算中的含义是: “一个符号(名义上写成下标,但实际上通常不写)在程序中单独或与其他人一起使用,以指定数组的元素之一。”
现在,在@user2194711 给出的简单示例中,我们可以看到附加元素不能成为列表的一部分,原因有两个:-
1) 我们并没有真正调用 append 方法;因为它需要()
来调用它。
2) 错误表示函数或方法不可下标;意味着它们不像列表或序列那样可索引。
现在看到这个:-
>>> var = "myString"
>>> def foo(): return 0
...
>>> var[3]
't'
>>> foo[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable
这意味着function
中没有下标或say 元素,就像它们按顺序出现一样;在[]
的帮助下,我们无法像我们一样访问它们。
还有;正如mipadi 在他的回答中所说的那样;它基本上意味着该对象实现了__getitem__()
方法。 (如果它是可下标的)。
因此产生了错误:
arr.append["HI"]
TypeError: 'builtin_function_or_method' 对象不可下标
【讨论】:
【参考方案3】:作为此处先前答案的推论,这通常表明您认为自己有一个列表(或字典,或其他可下标的对象),而实际上却没有。
例如,假设您有一个应该返回列表的函数;
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
现在,当您调用该函数,而 something_happens()
出于某种原因没有返回 True
值时,会发生什么? if
失败,所以你失败了; gimme_things
没有显式地 return
任何东西——所以事实上,它会隐式地 return None
。然后这段代码:
things = gimme_things()
print("My first thing is 0".format(things[0]))
将因“NoneType
object is not subscriptable”而失败,因为things
是None
,因此您尝试执行None[0]
这没有意义,因为...错误消息是什么说。
有两种方法可以修复代码中的这个错误——第一种是通过在尝试使用之前检查things
是否确实有效来避免错误;
things = gimme_things()
if things:
print("My first thing is 0".format(things[0]))
else:
print("No things") # or raise an error, or do nothing, or ...
或等效地捕获TypeError
异常;
things = gimme_things()
try:
print("My first thing is 0".format(things[0]))
except TypeError:
print("No things") # or raise an error, or do nothing, or ...
另一个是重新设计gimme_things
,以确保它始终返回一个列表。在这种情况下,这可能是更简单的设计,因为这意味着如果有很多地方存在类似的错误,它们可以保持简单和惯用。
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
else: # make sure we always return a list, no matter what!
logging.info("Something didn't happen; return empty list")
return []
当然,您在 else:
分支中添加的内容取决于您的用例。也许您应该在something_happens()
失败时引发异常,以使实际出错的地方更加明显和明确?在您自己的代码中添加异常是让您自己知道发生故障时确切情况的重要方法!
(还请注意,后一种修复方法仍然不能完全修复错误——它会阻止您尝试下标None
,但当things
是一个空列表时,things[0]
仍然是IndexError
。如果你有一个try
你也可以用except (TypeError, IndexError)
来捕获它。)
【讨论】:
【参考方案4】:在我的脑海中,以下是唯一可下标的内置函数:
string: "foobar"[3] == "b"
tuple: (1,2,3,4)[3] == 4
list: [1,2,3,4][3] == 4
dict: "a":1, "b":2, "c":3["c"] == 3
但是mipadi's answer 是正确的——任何实现__getitem__
的类都是可下标的
【讨论】:
【参考方案5】:我也有同样的问题。我在做
arr = []
arr.append["HI"]
所以使用[
会导致错误。应该是arr.append("HI")
【讨论】:
【参考方案6】:可编写脚本的对象是记录对其执行的操作并将它们存储为可重放的“脚本”的对象。
例如,请参阅:Application Scripting Framework
现在,如果 Alistair 不知道他问的是什么并且真正的意思是“可下标”对象(由其他人编辑),那么(正如 mipadi 也回答的那样)这是正确的:
可下标对象是任何实现__getitem__
特殊方法的对象(想想列表、字典)。
【讨论】:
请注意,我正在回答有关“可编写脚本”对象的原始问题,而不是其他人编辑的“可订阅”对象,而不是 Alistair。我真的希望 Alistair 发表评论。 啊,我收藏的新徽章! :) 开个玩笑,很明显。唯一证明编辑问题的理由是 Alistair 选择了一个答案。我仍然不确定 Alistair 是否确定要选择。以上是关于如果 Python 对象是“可下标的”,这意味着啥?的主要内容,如果未能解决你的问题,请参考以下文章
我听说 Python 有自动“垃圾收集”,但 C++ 没有。这意味着啥?