基本上问题是向用户隐瞒我的模块具有类实现的事实,以便用户可以像使用my_module.func()
假设我有一个模块my_module
和一个类MyThing
。例如:
# my_module.py
class MyThing(object):
def say():
print("Hello!")
在另一个模块中,我可能会这样做:
# another_module.py
from my_module import MyThing
thing = MyThing()
thing.say()
但是假设我不想做所有这些。我真正想要的是my_module
在import
上自动创建一个MyThing实例,以便我可以执行以下操作:
# yet_another_module.py
import my_module
my_module.say()
换句话说,无论我在模块上调用什么方法,我都希望它直接转发到包含在其中的类的默认实例。因此,对于模块的用户来说,似乎它中没有类,只是模块本身中的直接函数定义(其中函数实际上是包含在其中的类的方法)。那有意义吗?这样做有一个简短的方法吗?
我知道我可以在my_module
中执行以下操作:
class MyThing(object):
def say():
print("Hello!")
default_thing = MyThing()
def say():
default_thing.say()
但是假设MyThing
有很多" public"我想要使用的方法,然后我必须明确定义"转发"我不想做的每种方法的功能。
作为上述问题的扩展,有没有办法实现上面我想要的,但也能够使用像from my_module import *
这样的代码,并能够在另一个代码中直接使用MyThing
的方法模块,如say()
?
答案 0 :(得分:5)
在模块my_module
中执行以下操作:
class MyThing(object):
...
_inst = MyThing()
say = _inst.say
move = _inst.move
完全 random
module使用的模式。
自动执行此操作有点人为。首先,需要找出哪个实例/类属性是要导出的方法...可能只导出不以_
开头的名称,如
import inspect
for name, member in inspect.getmembers(Foo(), inspect.ismethod):
if not name.startswith('_'):
globals()[name] = member
然而,在这种情况下,我说明确比隐含更好。
答案 1 :(得分:2)
你可以直接替换:
def say():
return default_thing.say()
使用:
say = default_thing.say
您仍然需要列出转发的所有内容,但样板文件非常简洁。
如果您想用更自动的东西替换该样板,请注意(详细信息取决于Python版本),MyThing.__dict__.keys()
与['__dict__', '__weakref__', '__module__', 'say', '__doc__']
类似。所以原则上你可以迭代它,跳过__
Python内部,并在当前模块上调用setattr
(可用作sys.modules[__name__]
)。您可能会后悔没有在代码中明确列出这些内容,但您当然可以这样做。
或者你可以完全摆脱类,因为使用模块作为封装单位。只要对象上有数据,就用全局变量替换它。 “但是”,你可能会说,“我被警告不要使用全局变量,因为它们会导致问题”。坏消息是你已经创建了一个全局变量default_thing
,所以这艘船已经航行了。更糟糕的消息是,如果对象上有任何数据,那么你想要做的整个概念:改变共享全局状态的模块级函数,带有全局变量的大部分问题。
答案 2 :(得分:0)
不确定为什么这不起作用。
say = MyClass().say()
from my_module import *
say
>>Hello!