Python模块可以有__repr__吗?

7

一个Python模块可以有__repr__吗?想法是做类似这样的事情:

import mymodule
print mymodule

编辑:精度:我指的是用户自定义的repr!

5个回答

11

简短回答: 基本上答案是否定的。

但是你不能使用文档字符串找到你要查找的功能吗?

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

长答案:

你可以在模块级别上定义自己的 __repr__(只需提供 def __repr__(...),但是这样你就必须执行:

import mymodule
print mymodule.__repr__() 

为了获得您想要的功能,请看下面的Python Shell会话:

>>> 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)>"

我认为问题在于这些槽装饰器对象。根据链接所说,它们绕过了通常的“Python”查找项属性的方式。

对于这些类方法,CPython返回指向这些对象上相应方法的C指针(然后将其包装在槽装饰器对象中以便从Python端进行调用)。


我很想听Alex Martelli的解释;-) - ChristopheD
Christophe:我来帮你省点事吧,他告诉过我原因了,参见https://dev59.com/KHNA5IYBdhLWcg3wL6sc和https://dev59.com/JUrSa4cB1Zd3GeqPVEk5#1725968。 - Roger Pate

9
你可以通过转向黑暗面来实现这个效果。在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__])

看这里:

>>> import mymodule
>>> print mymodule
ABCDEFGHIJKLMNOQ

我模糊地记得,在之前类似的恶意黑客尝试中,设置特殊属性如 __class__ 时遇到了麻烦。但是在测试这个代码时,我没有遇到这个问题。如果你遇到这个问题,只需捕获异常并跳过该属性即可。


1
这是最好的答案,可惜排名不高。此外,在我看来,这并不是真正的“邪恶”黑客:你在系统级别上改变的唯一值是模块本身的名称。我认为模块的所有者应该能够安全地调整与该模块相关的任何内容。 - Mike Williamson

6

模块可以拥有__repr__函数,但在获取模块的表示时不会调用它。

所以,不,你不能做你想做的事情。


2
事实上,许多模块确实有一个__repr__方法!
>>> import sys
>>> print(sys)
<module 'sys' (built-in)>    #read edit, however, this info didn't come from __repr__ !

同时尝试使用dir(sys)查看是否有__repr__以及__name__等内容。

编辑:
在Python 3.0及以上版本中,__repr__似乎可以在模块中找到。
正如Ned Batchelder所指出的那样,当Python打印模块时,该方法并未被使用。(通过重新分配repr属性的快速实验证明了这一点...)


1
repr 不在我的 sys 属性中(Python 2.6.2) - ChristopheD
说句实话,在我的Python(2.5.1)中,我找到了sys.__repr__,但我认为它不是使用print(sys)打印出来的内容。 - Chris Lutz
1
在Python 2.6.2中,__repr__不在dir(sys)sys.__dict__中。然而,在sys.__class__.__dict__中它是一个有效的键(<slot wrapper '__repr__' of 'module' objects>)。 - ChristopheD

1
不行,因为__repr__是一个特殊的方法(我称之为能力),它只会在类上查找。你的模块只是模块类型的另一个实例,所以无论你如何定义__repr__,它都不会被调用!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接