Re: Question regarding unexpected behavior in using __enter__ method

2023-04-21 Thread Lorenzo Catoni
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  wrote:

> On 21Apr2023 00:44, Lorenzo Catoni  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 
> --
> https://mail.python.org/mailman/listinfo/python-list
>
-- 
https://mail.python.org/mailman/listinfo/python-list


Question regarding unexpected behavior in using __enter__ method

2023-04-20 Thread Lorenzo Catoni
Dear Python Mailing List members,

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.

On the other hand, when I implemented a custom function in place of the
__enter__ method, I encountered the following TypeError:

```
>>> def myint(*a, **kw):
... return int(*a, **kw)
...
>>> class X:
... __enter__ = myint
... __exit__ = lambda *_: None
...
>>> with X() as x:
... pass
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in myint
TypeError: int() argument must be a string, a bytes-like object or a real
number, not 'X'
```
Here, the TypeError occurred because "self" was passed as an input
parameter to "myint". Can someone explain why this unexpected behavior
occurs only in the latter case?

I tested this issue on the following Python versions, and the problem
persists on all of them:
- Python 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0] on linux
- Python 3.10.10 (main, Feb  8 2023, 14:50:01) [GCC 9.4.0] on linux
- Python 3.10.7 (tags/v3.10.7:6cc6b13, Sep  5 2022, 14:08:36) [MSC v.1933
64 bit (AMD64)] on win32

I appreciate any input or insights that you might have on this matter.

Thank you for your help in advance!

Best regards,
Lorenzo Catoni
-- 
https://mail.python.org/mailman/listinfo/python-list