可以用 Python 写只暴露一个 function 的模块吗?
如果你是问在 module 中定义多个函数并选择性地暴露其中一个的话,答案是「严格来说不可以」。你可以用单下划线来定义 module 的私有成员,从而防止它们被自动导入:#file 'test.py'
def foo():
print 'foo'
def _bar():
print '_bar'
此时 from test import * 只会导入 foo,而 import test 只会导入 test.foo 。但是你仍旧无法阻止别人显式地 from test import _bar 。详细原因参见 一个 Pythonic 的类应不应该在 __init__ 中检查参数有效性? 中的答案。
又或者你可以只在 module 里定义单一一个函数,所需其他函数均在此类中定义。
#file 'test.py'
def foo():
def bar():
print 'bar in foo'
bar()
又或者既然 class 可以写成 callable 的,那也可以当作函数用:
#file 'test.py'
def Foo(object):
def __call__(self):
print "foo"
#__main__:
>>> from test import *
>>> f = Foo()
>>> f()
foo
Python 里面 module 不能成为 callabe object,所以如果要让 module 能当函数用,必须自己去改被 import 进去的 namespace 的模块列表:
#test.py
import sys
def foo():
print "foo"
sys.modules[__name__] = foo
#__main__:
>>> import test
>>> test()
foo
这样做太过 hacky,请不要这样做。
当然还有更 hacky 的方法:CPython 判断某 object 是否 callable,是查看其类型之 _typeobject 成员的 tp_call 函数指针是否为 NULL(见 cpython: 8d4cace71113 Objects/abstract.c )。那么就可以利用 ctypes 级别修改 module 依赖的 PyTypeObject,使其 tp_call 指针指向有意义的函数,从而让 module 也变得 callable,详见 http://www.slideshare.net/r1chardj0n3s/dont-do-this-24000445 第70页开始的内容。但是也请不要这样做。
原发布于 https://www.zhihu.com/question/23185059/answer/23848076