113

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.

5
  • thanks for the answers but in case of comparison like items[i].v <8 how do I do it, I just tried using a temporary variable to store its value and then use this for comparison like temp = items[i].v then temp<8. Commented Mar 22, 2014 at 7:51
  • There is no need to take special measures when accessing a namedtuple's attributes. Commented Mar 22, 2014 at 8:05
  • there is no problem with accessing but i cant reassign it and i understand that and its same reason why i cant use it for comparison like i mentioned items[i].v]<8 . I need to know any better alternative like the one in answer using ._replace() Commented Mar 22, 2014 at 8:18
  • Using it in an expression does not require replacing it. Commented Mar 22, 2014 at 8:19
  • yea it worked, dunno then why I was getting an error at that statement before :C Commented Mar 22, 2014 at 8:27

7 Answers 7

154

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()
Sign up to request clarification or add additional context in comments.

4 Comments

Small note: For this to work in Python 2 you need to make Test a "new-style" class , i.e. explicitly derive from object(the first line must read class Test(object):. See also stackoverflow.com/a/45062077/1753435
I'm having this issue but with a list property and cannot figure out how to clear the list, any ideas? @Azmisov
@Ahmad I'd need more details, you should create a new question
Hi @Azmisov it is added here stackoverflow.com/questions/74827320/…
85
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")

13 Comments

Why?⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
@IgnacioVazquez-Abrams more explanation is required in this answer. (linking to the docs is not sufficient.)
TLDR; This is a valid solution. The leading underscore in the function _replace was not meant to indicate internal usage.
|
75

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)

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

3 Comments

yes after 10 mins i did what you told in the latter, and now I understand why this works but what I was doing before. Thnx
namedtuples are immutable - hits it on the nail. thanks
"Use a different data structure, e.g. a class" -- possibly a @dataclass?
4

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

1 Comment

yes, finally the right answer, thank you!
1

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

Comments

0

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()

Comments

-2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.