How to implement __setattr__ without infinite recursion

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
pagano.paganino
Posts: 89
Joined: Fri Sep 11, 2015 10:47 pm
Location: Italy

Re: How to implement __setattr__ without infinite recursion

Post by pagano.paganino » Thu Oct 03, 2019 8:52 am

@jimmo into the issue : py: object base class doesn't implement __setattr__ and __delattr__ #2755 i have already implemented this, can be this reuse?

Jongy
Posts: 9
Joined: Fri Jun 08, 2018 11:50 am

Re: How to implement __setattr__ without infinite recursion

Post by Jongy » Sun Dec 08, 2019 11:23 pm

jimmo wrote:
Thu Oct 03, 2019 8:43 am
pythoncoder wrote:
Thu Oct 03, 2019 7:37 am
@jimmo These are clever solutions but a naive Python programmer would expect to use object.__setattr__() to break the recursion. Would implementing this be a major problem?
Oh yeah, wholeheartedly agree!! Just got distracted by the puzzle, but I have already started doing exactly that (implementing object.__setattr__).
Well, where's the PR? :D

I wrote a piece of code today that worked nicely in CPython. It took a while to learn this object.__setattr__ trick. Anyway, I was quite sad when I got the first "AttributeError: 'super' object has no attribute '__setattr__'" exception.

Lucky I found this thread! I feel more okay now knowing that I wasn't fighting Python for nothing. Something's really missing.

I'd be happy to add it if you haven't got to it yet.

Jongy
Posts: 9
Joined: Fri Jun 08, 2018 11:50 am

Re: How to implement __setattr__ without infinite recursion

Post by Jongy » Sun Dec 08, 2019 11:44 pm

Okay I patched something quick and it seems to work. It's late so I'll tidy it up and open a PR tomorrow.
I added an "object.__setattr__" function that basically does "mp_map_lookup(&self->members, attr, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;".

The following code now works:

Code: Select all

class X(object):
    def __init__(self):
        object.__setattr__(self, "y", 5)

    def __setattr__(self, attr, value):
        print(attr, "=", value)
An X object is created, nothing is printed and it has a "y" attribute.

"super(X, self).__setattr__" doesn't work yet though :( If I define it as a static method then object.__setattr__ works but the "super" trick doesn't.
If I remove the static method, then "super(X, self).__setattr__" works but object.__setattr__ is now rejected with "TypeError: argument should be a 'object' not a 'X'".



Post Reply