Thankyou for your answer, i think i found the reason for this behavior, is has to do with the function being user defined or not, rather than being a plain function or type, as stated here https://docs.python.org/3/reference/datamodel.html#:~:text=Also%20notice%20that%20this%20transformation%20only%20happens%20for%20user%2Ddefined%20functions%3B%20other%20callable%20objects%20(and%20all%20non%2Dcallable%20objects)%20are%20retrieved%20without%20transformation
Regards, Lorenzo Catoni On Fri, 21 Apr 2023 at 07:21, Cameron Simpson <c...@cskk.id.au> wrote: > On 21Apr2023 00:44, Lorenzo Catoni <l.catoni...@gmail.com> wrote: > >I am writing to seek your assistance in understanding an unexpected > >behavior that I encountered while using the __enter__ method. I have > >provided a code snippet below to illustrate the problem: > > > >``` > >>>> class X: > >... __enter__ = int > >... __exit__ = lambda *_: None > >... > >>>> with X() as x: > >... pass > >... > >>>> x > >0 > >``` > >As you can see, the __enter__ method does not throw any exceptions and > >returns the output of "int()" correctly. However, one would normally > expect > >the input parameter "self" to be passed to the function. > > My descriptor fu is weak, but I believe this is because `int` is not a > plain function but a type. > > Consider this class definition: > > class X: > x = 1 > def y(self): > return "y" > > When you define a class, the body of the class is run in a namespace, > and on completion, the namespace is _used_ to construct the class. > During that process, the various names are considered. Here we've got 2 > names: "x" and "y". > > "x" refers to an int and is just stored as a class attribute, unchanged. > > "y" refers to a function, and is promoted to a descriptor of an unbound > method. > > So later: X.x return 1 but X.y returns a unbound method. If we make an > instance: > > objx = X() > > then obj.x returns 1 (by not fining an "x" on "obj", but finding one on > "type(obj)" i.e. the class attribute. > > By contrast, obj.y returns a bound method, a function already curried > with a leading parameter "obj" (which will be "self"). There's no "y" > attribute directly on "obj" but there's an unbound method on > "type(obj).y", which gets bound by saying "obj.y". > > The means that what happens to a name when you define the class depends > on the typeof the value bound to the name. > > A plain function gets turned into an unbound instance method, but other > things are left alone. > > When you went: > > __enter__ = int > > That's not a plain function and so "obj.__enter__" doesn't turn into a > bound method - it it just `int`. > > Cheers, > Cameron Simpson <c...@cskk.id.au> > -- > https://mail.python.org/mailman/listinfo/python-list > -- https://mail.python.org/mailman/listinfo/python-list