Reputation: 1445
Here is my code
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
In the last line I cant set the items[node.ind].v
value to node.v
as I want, and am getting the error
"AttributeError: can't set attribute"
I don't know what's wrong but it must be something based on syntax as using statements like node.v+=1
is also showing same error. I'm new to Python, so please suggest a way to make the above change possible.
Upvotes: 112
Views: 297096
Reputation: 8904
For anyone else Googling in to this message, I got this error due to a copy/paste error. The def method for the setter didn't exist with the correct name. For example:
def __init__(self,a):
self.a = a
...
@property
def a(self):
return self._a
@a.setter
def b(self, value): # Should have used a(self,value):
self._a = value
Upvotes: -2
Reputation: 111
In addition to this answer that Azmisov provided, adding a setter would solve the problem:
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
@attr.setter
def attr(self, value):
self._attr = value
Test()
Upvotes: 0
Reputation: 121966
namedtuple
s are immutable, just like standard tuples. You have two choices:
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)
If you want the latter, Ignacio's answer does the same thing more neatly using baked-in functionality.
Upvotes: 75
Reputation: 1629
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
Upvotes: 1
Reputation: 446
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
Upvotes: 4
Reputation: 7253
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()
Upvotes: 153
Reputation: 798546
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")
Upvotes: 85