AttributeError: 无法在 python 中设置属性

这是我的密码

N = namedtuple("N", ['ind', 'set', 'v'])
def solve():
items=[]
stack=[]
R = set(range(0,8))
for i in range(0,8):
items.append(N(i,R,8))
stack.append(N(0,R-set(range(0,1)),i))
while(len(stack)>0):
node = stack.pop()
print node
print items[node.ind]
items[node.ind].v = node.v

在最后一行,我不能设置的 items[node.ind].v值为 node.v,因为我想,并得到了错误

"AttributeError: can't set attribute"

我不知道出了什么问题,但肯定是基于语法的,因为使用像 node.v+=1这样的语句也会出现同样的错误。我是 Python 的新手,所以请提出一个方法来使上面的更改成为可能。

223470 次浏览
items[node.ind] = items[node.ind]._replace(v=node.v)

(Note: Don't be discouraged to use this solution because of the leading underscore in the function _replace. Specifically for namedtuple some functions have leading underscore which is not for indicating they are meant to be "private")

namedtuples are immutable, just like standard tuples. You have two choices:

  1. Use a different data structure, e.g. a class (or just a dictionary); or
  2. Instead of updating the structure, replace it.

The former would look like:

class N(object):


def __init__(self, ind, set, v):
self.ind = ind
self.set = set
self.v = v

And the latter:

item = items[node.ind]
items[node.ind] = N(item.ind, item.set, node.v)

Edit: if you want the latter, Ignacio's answer does the same thing more neatly using baked-in functionality.

For those searching this error, another thing that can trigger AtributeError: can't set attribute is if you try to set a decorated @property that has no setter method. Not the problem in the OP's question, but I'm putting it here to help any searching for the error message directly. (if you don't like it, go edit the question's title :)

class Test:
def __init__(self):
self._attr = "original value"
# This will trigger an error...
self.attr = "new value"
@property
def attr(self):
return self._attr


Test()

This error can be triggered if you try to redefine a member variable that is already defined in the class you inherited.

from pytorch_lightning import LightningModule


class Seq2SeqModel(LightningModule):
def __init__(self, tokenizer, bart, hparams):
super().__init__()
self.tokenizer = tokenizer
self.bart: BartForConditionalGeneration = bart
self.hparams = hparams  # This triggers the error
# Changing above line to below removes the error
# self.hp = hparams

As I was new to PyTorch and PyTorch Lightning, I did not know the LightningModule already had a member variable named self.hparams. As I tried to overwrite it in my code, it caused AttributeError: can't set attribute.

Just simply renaming my variable from self.hparams to something else removed the error.

Not the problem in the OP's question, but I'm putting it here to help any searching for the error message directly

I came across this when I incorrectly mixed dataclass and NamedTuple. Posting this here to potentially save someone from tearing out their hair.

@dataclasses.dataclass
class Foo(typing.NamedTuple):
bar: str