tags:

views:

259

answers:

5

Can a python module have a __repr__? The idea would be to do something like:

import mymodule
print mymodule

EDIT: precision: I mean a user-defined repr!

+2  A: 

As a matter of fact, many modules do [have a __repr__]!

>>> import sys
>>> print(sys)
<module 'sys' (built-in)>    #read edit, however, this info didn't come from __repr__ !

also try dir(sys) to see __repr__ is there along with __name__ etc..

Edit:
__repr__ seems to be found in modules, in Python 3.0 and up.
As indicated by Ned Batchelder, this methods is not used by Python when it print out the a module. (A quick experiment, where the repr property was re-assigned showed that...)

mjv
__repr__ is not in my sys attributes (python 2.6.2)
ChristopheD
For what it's worth, I found `sys.__repr__` in my Python (2.5.1), but I do think that it's not what gets printed out with `print(sys)`.
Chris Lutz
In python 2.6.2 `__repr__` is not in `dir(sys)` or `sys.__dict__`. However, it is a valid key in `sys.__class__.__dict__' (`<slot wrapper '__repr__' of 'module' objects>`).
ChristopheD
@ChristopheD - Same in 2.5.1. Curiouser and curiouser...
Chris Lutz
+3  A: 

Modules can have a __repr__ function, but it isn't invoked when getting the representation of a module.

So no, you can't do what you want.

Ned Batchelder
Any other idea?
static_rtti
+6  A: 

Short answer: basically the answer is no.

But can't you find the functionality you are looking for using docstrings?

testmodule.py
""" my module test does x and y
"""
class myclass(object):
    ...
test.py
import testmodule
print testmodule.__doc__

Long answer:

You can define your own __repr__ on a module level (just provide def __repr__(...) but then you'd have to do:

import mymodule
print mymodule.__repr__()

to get the functionality you want.

Have a look at the following python shell session:

>>> import sys                 # we import the module
>>> sys.__repr__()               # works as usual
"<module 'sys' (built-in)>"
>>> sys.__dict__['__repr__']     # but it's not in the modules __dict__ ?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: '__repr__'
>>> sys.__class__.__dict__['__repr__'] # __repr__ is provided on the module type as a slot wrapper
<slot wrapper '__repr__' of 'module' objects>
>>> sys.__class__.__dict__['__repr__'](sys) # which we should feed an instance of the module type
"<module 'sys' (built-in)>"

So I believe the problem lies within these slot wrapper objects which (from what can be read at the link) have the result of bypassing the usual 'python' way of looking up item attributes.

For these class methods CPython returns C pointers to the corresponding methods on these objects (which then get wrapped in the slot wrapper objects to be callable from the python-side).

ChristopheD
Cool idea, thanks!
static_rtti
I'd be interested in hearing Alex Martelli's explanation ;-)
ChristopheD
Christophe: I'll save you the trouble, as he told me why, see http://stackoverflow.com/questions/1060796/callable-modules and http://stackoverflow.com/questions/1725515/can-a-python-module-have-a-repr/1725968#1725968.
Roger Pate
+1  A: 

No, because __repr__ is a special method (I call it a capability), and it is only ever looked up on the class. Your module is just another instance of the module type, so however you would manage to define a __repr__, it would not be called!

kaizer.se
+3  A: 

You can achieve this effect--if you're willing to turn to the Dark Side of the Force.

Add this to mymodule.py:

import sys

class MyReprModule(mymodule.__class__):
  def __init__(self, other):
    for attr in dir(other):
      setattr(self, attr, getattr(other, attr))

  def __repr__(self):
    return 'ABCDEFGHIJKLMNOQ'

# THIS LINE MUST BE THE LAST LINE IN YOUR MODULE
sys.modules[__name__] = MyReprModule(sys.modules[__name__])

Lo and behold:

>>> import mymodule
>>> print mymodule
ABCDEFGHIJKLMNOQ

I dimly remember, in previous attempts at similarly evil hacks, having trouble setting special attributes like __class__. I didn't have that trouble when testing this. If you run into that problem, just catch the exception and skip that attribute.

Larry Hastings