【问题标题】:Python class is subscriptable but not iterablePython 类可下标但不可迭代
【发布时间】:2019-07-06 16:20:33
【问题描述】:

我正在尝试公开 classes 字典,使其既可下标,又能够遍历 dict 值。这是课程:

class ExampleClass():
    def __init__(self, *args, **kwargs):
        for key, value in self.kwargs.items():
            setattr(self, key, value)
        for arg in args:
            setattr(self, arg, arg) if isinstance(arg, str) else setattr(self, str(arg), arg)
    def __str__(self):
        return 'This is the example class'
    def __getitem__(self, obj):
        return self.__dict__[obj]
    def __len__(self):
        return len(self.__dict__.items())

如果我们创建一个实例并传入这些值:

cls = ExampleClass(123456,'cash', name='newexample', id=1)

这会将所有 args 和 kwargs 存储为实例属性,并且使用语法 cls['id'] 将按预期返回 1。但是当我使用语法 for i in cls: print(i) 我得到一个 KeyError :KeyError : 0

如何使这个对象的 dict 既可下标又可迭代?

【问题讨论】:

  • 需要实现__iter__函数来开启可迭代性

标签: python class dictionary object


【解决方案1】:

你需要实现 __iter__ 方法。

class ExampleClass():
    def __init__(self, *args, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
        for arg in args:
            setattr(self, arg, arg) if isinstance(arg, str) else setattr(self, str(arg), arg)
    def __str__(self):
        return 'This is the example class'
    def __getitem__(self, obj):
        return self.__dict__[obj]
    def __len__(self):
        return len(self.__dict__.items())
    def __iter__(self):
        return iter(self.__dict__)

cls = ExampleClass(123456,'cash', name='newexample', id=1)
print(cls['cash'])
print(cls['name'])
for i in cls: print(i)

这个方法被调用来为你的类型创建一个迭代器,以便它可以被迭代。你的底层字典已经实现了它,所以你只是在这里代理它。

【讨论】:

  • 我们还应该注意,您的代码修复了问题中的self.kwargs 错误
  • 谢谢@paulprescod 我以为我需要__iter____next__ 预定义变量来完成这项工作,但不知道怎么做!
  • 为了清楚起见,您实际上并不需要实现__iter__。如果您的 __getitem__ 可以接受从 0 开始到您的实例长度的整数就足够了。
  • 另外@Paul 解决方案将打印键,但我如何打印值?
  • @jakuta:你想要使用对象的代码来打印值吗?如果是这样,那么您只需要查看for i in cls: print(i, cls[i]) 或者您是否希望对象本身始终返回键/值对?如果是这样,我建议您实现一个 items() 方法来模拟 Python 中字典的工作方式。 __iter__ 也可以返回元组,但您不妨复制 IMO 字典的工作方式。如果您确实需要 __iter__ 来返回元组,那么它的主体看起来更像return iter(self.__dict__.items())
【解决方案2】:

要使一个类可下标,它必须包含 dunder getitem(),它可能包含也可能不包含 dunder iter()。

同时,一个可迭代对象必须包含 iter()。

要检查您的类是否具有所需的方法,请执行print(dir(your_class)),并查找相应的 dunder 函数。

如果您没有,请创建它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 2016-04-06
    相关资源
    最近更新 更多