`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 像 int
、float
、list
等等没有。这是一种优化,因为否则这些 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]
具有所需的行为。
出于某种原因,这在 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 像 int
、float
、list
等等没有。这是一种优化,因为否则这些 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]
具有所需的行为。