I think there's been some confusion with regard to this idea, leading to a
combination of technical details vs the merits of the idea.

So I'm going to summarize a bit what I think the discussion has yielded:

Technical issues:

The __repr__ and __str__ are defined on the class, not instances of a class.

You cannot override them in an instance.

modules are instances of the module class.

Thus the only way to change the __repr__ or __str__ (or other magic
methods) is to create a custom subclass of the module class.

Design issues:

You probably don't want to change the __repr__ of a module anyway -- there
are good reasons to keep the repr of all modules the same and standardized.
(which is one reason __repr__'s are defined on the class, not the instance,
you generally wouldn't want different instances of classes to have
different __repr__s (or any other different magic method behavior).

And while customizing the __repr__ of a module to be non standard is a bad
idea, it's not such a bad idea to customize the __str__ of a module --
traditionally that's where you put a more human-readable version of an
object.

But: modules are kind of special: in the VAST majority of the time, the
instances are created by the import mechanism, which the user has little
control over. And the writer of the module even less. In many cases, one
could write a custom subclass of a standard type, and have your code run
that instead of the usual type, and your users would get that custom class,
but it's difficult to do that with modules.

You can define a custom module class by subclassing types.ModuleType. And
you could put that custom module in a __init__.py of a package, and then be
able to do:

from the_package import the_module

and then the_module will have a custom __str__

Here that is, in action:

in module_str/__init__.py:

import types

class StrModule(types.ModuleType):
    def __init__(self, name, custom_str):
        super().__init__(name)
        self.___str__ = custom_str

    def __str__(self):
        return f"module {self.__name__}: {self.___str__}"


# create a new module with a custom string representation:
a_module = StrModule("a_module", "a custom str() for a_module" )


# put a few things into it
a_module.x = 5

def a_function():
    return "a_function was called"

a_module.a_function = a_function

the use it:

"""
test code for a custom string module
"""

from module_str import a_module

print("the repr of the module:", repr(a_module))

print("the str of the module:", str(a_module))

print("and it works:")

print(a_module.x)
print(a_module.a_function())

Which when run:

$ python try_module_str.py
the repr of the module: <module 'a_module'>
the str of the module: module a_module: a custom str() for a_module
and it works:
5
a_function was called

If one really wanted to do this, you could populate the module with the
contents of a another regular module, so that you'd only need to do this
special trick in the __init__, and the rest of your module writing would be
the same.

However, I can't figure out how to provide a custom __str__ for a package
(i.e. the __init__ itself) that could be imported in the regular way.

So: you can, with standard Python, make modules (if not packages) with a
custom str() ( or repr(), but it seems there is consensus that that's not a
good idea). But it's pretty awkward.

So if folks think it's a good idea to allow modules to have a custom
__str__: it would be nice to add that feature to Python.

I'm not saying I advocate for that -- but it's not completely unreasonable.

-CHB

-- 
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@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/I6AQY3A56JXKQCNNI6AEXOPYM4N6XZ57/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to