An instance of object creation occurs when a reference to a bound method is created

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

An instance of object creation occurs when a reference to a bound method is created

Post by jickster » Wed Jun 20, 2018 8:59 pm

Code: Select all

class Some(object): pass
dir(Some)
On Windows, output is
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
On micropython,
['__qualname__', '__module__']
Last edited by jickster on Thu Jun 21, 2018 5:50 pm, edited 1 time in total.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: dir(SomeClass) only has two entries

Post by pythoncoder » Thu Jun 21, 2018 7:57 am

Have you studied this doc?
Peter Hinch
Index to my micropython libraries.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: dir(SomeClass) only has two entries

Post by jickster » Thu Jun 21, 2018 2:46 pm

pythoncoder wrote:
Thu Jun 21, 2018 7:57 am
Have you studied this doc?
Why does an allocation occur where the comment says it does?

Code: Select all

class Foo():
    def __init__(self):
        self.bar_ref = self.bar  # Allocation occurs here
        self.x = 0.1
        tim = pyb.Timer(4)
        tim.init(freq=2)
        tim.callback(self.cb)

    def bar(self, _):
        self.x *= 1.2
        print(self.x)

    def cb(self, t):
        # Passing self.bar would cause allocation.
        micropython.schedule(self.bar_ref, 0)
I asked this on stackoverflow and they said it was because of descriptors but your link says descriptors are opt-in so . . .

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: dir(SomeClass) only has two entries

Post by stijn » Thu Jun 21, 2018 2:52 pm

jickster wrote:
Thu Jun 21, 2018 2:46 pm
Why does an allocation occur where the comment says it does?
Not sure what this has to do with the original question, but: why would it not allocate? You are creating a new instance member, you need memory for that. Same for the assignmet to self.x. There's not really a way around that, doesn't have anything to do with descriptors.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: dir(SomeClass) only has two entries

Post by jickster » Thu Jun 21, 2018 2:54 pm

stijn wrote:
Thu Jun 21, 2018 2:52 pm
jickster wrote:
Thu Jun 21, 2018 2:46 pm
Why does an allocation occur where the comment says it does?
Not sure what this has to do with the original question, but: why would it not allocate? You are creating a new instance member, you need memory for that. Same for the assignmet to self.x. There's not really a way around that, doesn't have anything to do with descriptors.
"creating a new instance member" - it's not creating a new member it's getting a reference to an existing instance member.

How are you creating anything?
Last edited by jickster on Thu Jun 21, 2018 3:08 pm, edited 1 time in total.

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: dir(SomeClass) only has two entries

Post by stijn » Thu Jun 21, 2018 3:08 pm

You're obtaining a reference (so you already need place on the stack to hold it), but you are also storing it into self.bar_ref. That's what needs memory. Sorry I don't know correct Python terminology well, but in any case: when the line with bar_ref gets executed, bare_ref is not yet a member of self. There's no trace of it, anywhere. All that happened so far is the interpreter/compiler created some intermediate structure which says 'when this line executes, store the attribute with name 'bare_ref' in whatever self uses to store attributes'. Which leads to a call to mp_obj_instance_store_attr, which in turn wil allocate memory for the hash map in which members like bare_ref and x are stored.

edit ok maybe theoretically it's possible to not have to allocate new memory with descriptor support (not sure, didn't test): if the self.bar_ref = self.bar would be forwarded to self.__set__('bar_ref', self.bar) and that implementation happens to use a preallocated structure to store things, no extra allocation would probably be needed.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: dir(SomeClass) only has two entries

Post by jickster » Thu Jun 21, 2018 3:32 pm

stijn wrote:
Thu Jun 21, 2018 3:08 pm
You're obtaining a reference (so you already need place on the stack to hold it), but you are also storing it into self.bar_ref. That's what needs memory. Sorry I don't know correct Python terminology well, but in any case: when the line with bar_ref gets executed, bare_ref is not yet a member of self. There's no trace of it, anywhere. All that happened so far is the interpreter/compiler created some intermediate structure which says 'when this line executes, store the attribute with name 'bare_ref' in whatever self uses to store attributes'. Which leads to a call to mp_obj_instance_store_attr, which in turn wil allocate memory for the hash map in which members like bare_ref and x are stored.
Everything you said makes sense.

But this uPy doc implies that the statement self.bar creates an object
An instance of object creation occurs when a reference to a bound method is created. This means that an ISR cannot pass a bound method to a function.
http://docs.micropython.org/en/latest/p ... on-objects

This means that an ISR cannot pass a bound method to a function - this implies that statement self.bar creates an object because the mere passing of a bound method triggers assignment operator.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: dir(SomeClass) only has two entries

Post by jickster » Thu Jun 21, 2018 5:52 pm

stijn wrote:
Thu Jun 21, 2018 2:52 pm
jickster wrote:
Thu Jun 21, 2018 2:46 pm
Why does an allocation occur where the comment says it does?
There's not really a way around that, doesn't have anything to do with descriptors.
The dotted attribute access self.bar is an invocation of descriptor __get__, creating a bound method.
https://stackoverflow.com/questions/509 ... hod-is-cre

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: dir(SomeClass) only has two entries

Post by stijn » Thu Jun 21, 2018 7:32 pm

jickster wrote:
Thu Jun 21, 2018 3:32 pm
But this uPy doc implies that the statement self.bar creates an object
Oops, missed that, thought the allocation you meant was for storing in self.bar_ref. But, yes, for a bound method an object has to be created (small one though, just pointer to method and pointer to self), see mp_obj_new_bound_meth which is wat will get called upon self.bar.
The dotted attribute access self.bar is an invocation of descriptor __get__, creating a bound method.
For CPython and maybe other Python implementations, but for MicroPython not every class has a predefined __get__ and mp_obj_instance_load_attr just ends up finding bar in locals_dict.

Post Reply