Python 对象是否“可订阅”意味着什么?

问题描述 投票:0回答:7

哪些类型的对象属于“可订阅”范围?

python terminology
7个回答
567
投票

它基本上意味着该对象实现了

__getitem__()
方法。换句话说,它描述的是“容器”对象,意味着它们包含其他对象。这包括字符串、列表、元组和字典。


111
投票

我突然想到,以下是唯一可订阅的内置函数:

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的答案是正确的 - 任何实现

__getitem__
的类都是可下标的


23
投票

下标在计算中的含义是: “在程序中单独或与其他符号一起使用的符号(理论上写为下标,但实际上通常不是),用于指定数组的元素之一。”

现在,在 @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
中没有下标或元素,就像它们出现在序列中一样;我们无法像平常那样在
[]
的帮助下访问它们。

还有;正如mipadi在他的回答中所说;它基本上意味着该对象实现了

__getitem__()
方法。 (如果它是可订阅的)。 因此产生了错误:

arr.append["HI"]

TypeError:“builtin_function_or_method”对象不可下标


20
投票

可编写脚本的对象是记录对其执行的操作的对象,并且可以将它们存储为可以重播的“脚本”。

例如,请参阅:应用程序脚本框架

现在,如果 Alistair 不知道他问的是什么,并且真正意味着“可订阅”对象(由其他人编辑),那么(正如 mipadi 也回答的那样)这是正确的:

可下标对象是实现

__getitem__
特殊方法的任何对象(想想列表、字典)。


12
投票

我也有同样的问题。我在做

arr = []
arr.append["HI"]

因此使用

[
会导致错误。应该是
arr.append("HI")


10
投票

作为此处早期答案的推论,这通常表明您认为自己有一个列表(或字典或其他可下标的对象),但实际上没有。

例如,假设您有一个函数应该返回一个列表;

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
对象不可下标”,因为,
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[0]
是空列表时,
IndexError
仍然是
things
。如果您有a
try
你也可以用
except (TypeError, IndexError)
来捕获它。)


0
投票

基本上,如果您在上述对象的类型转换之后修改或添加任何字段而不是之前执行此操作,则会出现此错误。

© www.soinside.com 2019 - 2024. All rights reserved.