python – 伪装一个类的真实模块

假设你有一个
python包的以下布局

./a
./a/__init__.py
./a/_b.py

你在__init__.py里面

from _b import *

你在_b.py里面

class B(object): pass

如果从交互式提示导入

>>> import a
>>> a.B
<class 'a._b.B'>
>>> 

我怎样才能完全隐藏_b的存在?

我试图解决的问题如下:我想要一个导入“隐藏”模块和类的Facade包.从外观(在我的情况下为a)中提供的类保持稳定并保证将来使用.但是,我希望自由地在“引擎盖下”重新定位类,因此隐藏模块.这一切都很好,但是如果一些客户端代码挑选了一个由Facade提供的对象,那么这个pickle数据将引用隐藏模块嵌套,而不是外观嵌套.换句话说,如果我在模块_c.py中重新定位B类,客户端代码将无法解开,因为pickle类指的是a._b.B,它已被移动.如果他们提到a.B,我可以根据需要重新定位B类,而不会破坏腌制数据.

最佳答案 尝试:

B.__module__= 'a'

顺便提一下,您可能想要绝对导入:

from a._b import *

因为没有新的显式点语法的相对导入将消失(see PEP 328).

ETA评论:

I would have to set the module explicitly for every class

是的,我认为没有办法解决这个问题但你至少可以在__init__结束时自动化它:

for value in globals().values():
    if inspect.isclass(value) and value.__module__.startswith('a.'):
        value.__module__= 'a'

(对于新式类,只有你可以使用isinstance(value,type)而不是inspect.如果模块不必以__main__运行,你可以使用__name__而不是硬编码’a’.)

点赞