Reputation: 13846
For some reason this fails in Python 3.8:
setattr(iter(()), '_hackkk', 'bad idea')
Error:
---------------------------------------------------------------------------
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'
How do I attach random data where I shouldn't, i.e., on an iterator or a generator?
Upvotes: 3
Views: 174
Reputation: 34367
You can attach data only to objects, which have __dict__
-member. Not all objects have it - for example builtin classes like int
, float
, list
and so on do not. This is an optimization, because otherwise instances of those classes would need too much memory - a dictionary has a quite large memory footprint.
Also for normal classes one could use __slots__
, thus removing __dict__
-member and prohibiting dynamic addition of attributes to an object of this class. E.g.
class A:
pass
setattr(A(),'b', 2)
works, but
class B:
__slots__ = 'b'
setattr(B(),'c', 2)
doesn't work, as class B
has no slot with name c
and no __dict__
.
Thus, the answer to your question is: for some classes (as the tuple_iterator
) you cannot.
If you really need to, you can wrap tuple_iterator
in a class with __dict__
and append the new attribute to the 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
and now:
iw=IterWrapper(iter((1,2,3)))
setattr(iw, "a", 2)
print(iw.a) # prints 2
print(list(iw)) # prints [1,2,3]
has the desired behavior.
Upvotes: 1