str(obj) not calling obj.__str__?
Hello, I just noticed that calling `str(x)` is actually doing (in CPython `PyObject_Str`) `type(x).__str__(x)` rather than `x.__str__()`. Context: I wanted to override __str__ for certain objects in order to “see them better”. I'm wondering why not do `x.__str__()` Best regards, -- Jérôme
This is explained in "Special Method Lookup": https://docs.python.org/3/reference/datamodel.html#special-method-lookup Short version: For both correctness and performance, special methods (those that begin and end with double underscores) are typically looked up on the class, not the instance. If you want to override on a per-instance level, have a non-special method that __str__ invokes, that can be overridden on a per-instance basis. On Sun, Feb 23, 2020 at 2:30 AM Jérôme Carretero <cj-python@zougloub.eu> wrote:
Hello,
I just noticed that calling `str(x)` is actually doing (in CPython `PyObject_Str`) `type(x).__str__(x)` rather than `x.__str__()`.
Context: I wanted to override __str__ for certain objects in order to “see them better”.
I'm wondering why not do `x.__str__()`
Best regards,
-- Jérôme _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/2VSTPA... Code of Conduct: http://python.org/psf/codeofconduct/
Thanks Josh for your prompt reply. All clear. Regards, -- Jérôme PS: Somehow I had never encountered a situation exacerbating the subtleties of implicit invocations of special methods, and hadn't read or integrated that section of the documentation, then when encountering the “problem” I didn't make my way to the docs. And now I also see that right when opening § 3.3. Special method names ¶ 1 it's stated that “`x[i]` is roughly equivalent to `type(x).__getitem__(x, i)`”. I'll be more careful next time! On Sun, 23 Feb 2020 02:35:24 +0000 Josh Rosenberg <shadowranger+pythonideas@gmail.com> wrote:
This is explained in "Special Method Lookup": https://docs.python.org/3/reference/datamodel.html#special-method-lookup
Short version: For both correctness and performance, special methods (those that begin and end with double underscores) are typically looked up on the class, not the instance. If you want to override on a per-instance level, have a non-special method that __str__ invokes, that can be overridden on a per-instance basis.
On Sun, Feb 23, 2020 at 2:30 AM Jérôme Carretero <cj-python@zougloub.eu> wrote:
Hello,
I just noticed that calling `str(x)` is actually doing (in CPython `PyObject_Str`) `type(x).__str__(x)` rather than `x.__str__()`.
Context: I wanted to override __str__ for certain objects in order to “see them better”.
I'm wondering why not do `x.__str__()`
Best regards,
-- Jérôme
In unittest.mock.MagicMock I solve this problem by having __new__ create a new subclass for every instantiation. Setting any magic method on the instance is promoted to the type via __setattr__. That way every instance can have unique magic methods without affecting other instances. Michael On Sun, 23 Feb 2020 at 04:21, Jérôme Carretero <cj-python@zougloub.eu> wrote:
Thanks Josh for your prompt reply. All clear.
Regards,
-- Jérôme
PS: Somehow I had never encountered a situation exacerbating the subtleties of implicit invocations of special methods, and hadn't read or integrated that section of the documentation, then when encountering the “problem” I didn't make my way to the docs. And now I also see that right when opening § 3.3. Special method names ¶ 1 it's stated that “`x[i]` is roughly equivalent to `type(x).__getitem__(x, i)`”. I'll be more careful next time!
On Sun, 23 Feb 2020 02:35:24 +0000 Josh Rosenberg <shadowranger+pythonideas@gmail.com> wrote:
This is explained in "Special Method Lookup": https://docs.python.org/3/reference/datamodel.html#special-method-lookup
Short version: For both correctness and performance, special methods (those that begin and end with double underscores) are typically looked up on the class, not the instance. If you want to override on a per-instance level, have a non-special method that __str__ invokes, that can be overridden on a per-instance basis.
On Sun, Feb 23, 2020 at 2:30 AM Jérôme Carretero <cj-python@zougloub.eu> wrote:
Hello,
I just noticed that calling `str(x)` is actually doing (in CPython `PyObject_Str`) `type(x).__str__(x)` rather than `x.__str__()`.
Context: I wanted to override __str__ for certain objects in order to “see them better”.
I'm wondering why not do `x.__str__()`
Best regards,
-- Jérôme
Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/G3MW5G... Code of Conduct: http://python.org/psf/codeofconduct/
-- Michael Foord Python Consultant, Contractor and Trainer https://agileabstractions.com/
On Sun, 23 Feb 2020 at 11:25, Michael Foord <fuzzyman@gmail.com> wrote:
In unittest.mock.MagicMock I solve this problem by having __new__ create a new subclass for every instantiation. Setting any magic method on the instance is promoted to the type via __setattr__. That way every instance can have unique magic methods without affecting other instances.
The other little bit of trickery is that MagicMock gets all the magic methods by default and they're all MagicMock objects. To avoid instantiating MagicMock recursively creating MagicMocks forever the magic methods are descriptors that put a new MagicMock instance onto the subclass on first access via an instance. I could probably have saved a lot of effort by overriding __getattribute__ (which can intercept magic method lookups unlike __getatttr__) instead of the descriptor solution. At the time I didn't know that. There's still a bunch of jiggery-pokery to set valid default return values on a bunch of the methods (some are type checked on the return value and some aren't *sigh*), so maybe it's unavoidable. I had fun getting mock to work. Michael
Michael
On Sun, 23 Feb 2020 at 04:21, Jérôme Carretero <cj-python@zougloub.eu> wrote:
Thanks Josh for your prompt reply. All clear.
Regards,
-- Jérôme
PS: Somehow I had never encountered a situation exacerbating the subtleties of implicit invocations of special methods, and hadn't read or integrated that section of the documentation, then when encountering the “problem” I didn't make my way to the docs. And now I also see that right when opening § 3.3. Special method names ¶ 1 it's stated that “`x[i]` is roughly equivalent to `type(x).__getitem__(x, i)`”. I'll be more careful next time!
On Sun, 23 Feb 2020 02:35:24 +0000 Josh Rosenberg <shadowranger+pythonideas@gmail.com> wrote:
This is explained in "Special Method Lookup":
https://docs.python.org/3/reference/datamodel.html#special-method-lookup
Short version: For both correctness and performance, special methods
that begin and end with double underscores) are typically looked up on
(those the
class, not the instance. If you want to override on a per-instance level, have a non-special method that __str__ invokes, that can be overridden on a per-instance basis.
On Sun, Feb 23, 2020 at 2:30 AM Jérôme Carretero <cj-python@zougloub.eu
wrote:
Hello,
I just noticed that calling `str(x)` is actually doing (in CPython `PyObject_Str`) `type(x).__str__(x)` rather than `x.__str__()`.
Context: I wanted to override __str__ for certain objects in order to “see them better”.
I'm wondering why not do `x.__str__()`
Best regards,
-- Jérôme
Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/G3MW5G... Code of Conduct: http://python.org/psf/codeofconduct/
--
Michael Foord
Python Consultant, Contractor and Trainer
-- Michael Foord Python Consultant, Contractor and Trainer https://agileabstractions.com/
participants (3)
-
Josh Rosenberg
-
Jérôme Carretero
-
Michael Foord