`setattr` 在 CPython 中因 `AttributeError` 失败?

`setattr` fails with `AttributeError` in CPython?

出于某种原因,这在 Python 3.8:

中失败了
setattr(iter(()), '_hackkk', 'bad idea')

错误:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-c046f8521130> in <module>
----> 1 setattr(iter(()), '_hackkk', 'bad idea')

AttributeError: 'tuple_iterator' object has no attribute '_hackkk'

如何在不应该​​附加随机数据的地方,即在迭代器或生成器上附加随机数据?

您只能将数据附加到具有 __dict__ 成员的对象。不是所有的对象都有它——例如内置的 classes 像 intfloatlist 等等没有。这是一种优化,因为否则这些 classes 的实例将需要太多内存 - 字典占用的内存非常大。

对于正常的 classes 也可以使用 __slots__,从而删除 __dict__-成员并禁止向此 class 的对象动态添加属性。例如

class A:
    pass
setattr(A(),'b', 2)

有效,但是

class B:
    __slots__ = 'b'
setattr(B(),'c', 2)

不起作用,因为 class B 没有名称为 c 的插槽,也没有 __dict__.

因此,您的问题的答案是:对于某些 classes(如 tuple_iterator),您不能。

如果确实需要,可以将 tuple_iterator 包装在带有 __dict__ 的 class 中,并将新属性附加到 wrapper-object:

class IterWrapper:
    def __init__(self, it):
        self.it=it
    def __next__(self):
        return next(self.it)   
    def __iter__(self): # for testing
        return self

现在:

iw=IterWrapper(iter((1,2,3)))
setattr(iw, "a", 2)
print(iw.a)          # prints 2
print(list(iw))      # prints [1,2,3]

具有所需的行为。