【问题标题】:List element (object) not subscriptable列表元素(对象)不可下标
【发布时间】:2020-10-10 19:09:27
【问题描述】:

我想为一个函数创建一个单元测试,该函数根据某些对象属性对对象列表进行排序。这是一个代码示例:

class Foo:
    """Custom data type Foo."""

    def __init__(self,
                 a: str,
                 b: int,
                 c: int,
                 d: int,
                 e: int,
                 f: int):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.f = f
        self.g = c * d * e
        self.h = c * d

这是产生错误的单元测试功能的一部分:

from random import randint
...
class Test(TestCase):

def test_item_sort_foo(self):
    random_list = [Foo(str(randint(0, 1000)),
                        randint(0, 100),
                        randint(0, 100),
                        randint(0, 100),
                        randint(0, 100),
                        randint(0, 100))
                   for x in range(100)]
...

错误信息是:

TypeError: 'Foo' object is not subscriptable. 

尽管阅读了this question,但我无法理解为什么 Python 会关心 Foo 是否可下标,因为 random_list 已经是可下标的。我正在尝试生成与答案here 类似的随机Foo 项目列表。我很困惑,因为我已经有一个(工作)类

from dataclasses import dataclass
from typing import List


@dataclass
class Bar:
    """Bar custom data type."""
    i: str
    j: List[Foo]

我可以输入,例如,

f = Foo(...)
b = Bar("baz", [])
b.j.append(f)

所以这是我的问题:

  • 可下标对象的元素也必须是可下标的吗?为什么?
  • 生成具有上述属性的随机数据进行测试的最佳方法是什么?
  • 如何将这一原则应用于我的案例?

编辑:这是完整的单元测试功能:

def test_item_sort_foo(self):
        random_list = [Foo(str(randint(0, 1000)),
                            randint(0, 100),
                            randint(0, 100),
                            randint(0, 100),
                            randint(0, 100),
                            randint(0, 100))
                       for x in range(100)]
        sorted_list = item_sort_foos(random_list)
        assert eq(sorted_list, sorted(random_list,
                                      key=itemgetter(4, 7),
                                      reverse=True))

下面是实现逻辑的函数代码:

def item_sort_foos(foos: List[Foo]) -> List[Foo]
    return sorted(foos,
                  key=attrgetter("e", "h"),
                  reverse=True)

EDIT2:完整的跟踪是:

Error
Traceback (most recent call last):
  File "/opt/anaconda3/lib/python3.7/unittest/case.py", line 59, in testPartExecutor
    yield
  File "/opt/anaconda3/lib/python3.7/unittest/case.py", line 628, in run
    testMethod()
  File ".../src/project/tests/test_orderings.py", line 89, in test_item_sort_foos
    reverse=True))
TypeError: 'Foo' object is not subscriptable

如果您需要任何其他信息,请在 cmets 中请求。

【问题讨论】:

  • 这个问题没有足够的代码来重现问题。
  • 我应该提供哪些额外信息?
  • 获得相同 TypeError 所需的一切。
  • 你能发布完整的回溯吗?在删除了一些杂乱无章的代码后,代码生成了 random_list 没问题。我认为您的问题出在其他地方。
  • Timgeb 是对的:您应该准确发布产生错误的代码和命令。其他人可以逐字运行并得到错误的东西。

标签: python list object pytest list-comprehension


【解决方案1】:

random_listFoo 对象的列表。当您使用key=itemgetter(4, 7) 的排序键时,您正在尝试索引 foo 对象本身。和它一样

foo = Foo(...)
sort_key = foo[4], foo[7]

您可能想在您正在测试的item_sort_foos 函数中使用key=attrgetter("e", "h")

但这是测试代码。 item_sort_foos 是一个非常小的函数,如果你所做的只是把它的胆量放在你的单元测试中,那么你还没有进行太多测试。相反,您应该传入一些您已经知道输出应该是什么的固定列表。比较一下。

【讨论】:

  • 确实,itemgetter 用错了。可能是括号问题;将编辑我的 q
  • 我没有得到“罐头”部分 - 随机元素的列表不是最佳实践吗?
  • 这是一个单元测试,它是“给定输入 A 期望输出 B”。如果您输入的是随机数,那么您真的不知道会发生什么,除非您只是第二次实施相同的算法。你想要多个测试。零项目会发生什么? 1 项? 5个已知排序的项目?比较相同的几个项目?这些都将产生先前确定的输出。 100 个项目如何真正测试任何东西,尤其是在没有预定输出的情况下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2022-08-14
  • 2020-01-29
  • 1970-01-01
  • 2020-06-28
  • 1970-01-01
相关资源
最近更新 更多