好吧,这有点复杂。
假设我在包中有一个模块:
a_package
|-- __init__.py
|-- a_module.py
在 a_module.py 中,我声明了 A_Class:
# file location: a_package/a_module.py
class A_Class():
def say(self):
print ("cheese")
我可以创建一个 A_Class 实例并调用 say 方法:
from a_package.a_module import A_Class
my_object = A_Class()
my_object.say() # this will display 'cheese' as expected
但是,我想做一个更动态的方式(我打算有很多包和类,并且想让代码更容易写)。所以,我创建了一个名为 load_class
def load_class(package_name, module_name, class_name)
result = None
try:
exec('from ' + package_name + '.' + module_name + ' import ' + class_name)
exec('result = '+class_name)
except:
raise ImportError('Unable to load the class')
return result
# Now, I can conveniently do this:
A_Class = load_class('a_package', 'a_module', 'A_Class')
my_object = A_Class()
my_object.say()
# or even shorter:
load_class('a_package', 'a_module', 'A_Class')().say()
程序按预期工作,但 IDE(我使用 pydev)不理解我的代码,无法执行智能感知(自动完成代码)。
如果我使用第一种方法,智能感知显然是有效的:
from a_package.a_module import A_Class
my_object = A_Class()
my_object. # when I press ".", there will be a popup to let me choose "say" method
但如果我使用第二种方法,智能感知无法为我完成:
load_class('a_package', 'a_module', 'A_Class')(). # when I press ".", nothing happened
我知道,这是在 Python 中进行动态导入的权衡。但是,我想知道是否有一些替代方法让我做第二种方法(可能不使用 exec)仍然可以让通用 IDE(例如 Pydev)的智能感知猜测里面的方法类?
编辑:为什么我需要这样做? 假设我有这样一个目录结构
fruit
|-- strawberry.py
|-- orange.py
chocolate
|-- cadbury.py
|-- kitkat.py
need_dynamic.py
在 need_dynamic.py 中,我有这个脚本:
food_list = ['fruit', 'chocolate']
subfood_list = [['strawberry', 'orange'],['cadbury', 'kitkat']]
# show food list and ask user to choose food
for i in xrange(len(food_list)):
print i + " : " + food_list[i]
food_index = int(raw_input('chose one'))
# show subfood list and ask user to choose subfood
for i in xrange(len(subfood_list[food_index])):
print i + " : " + subfood_list[food_index][i]
subfood_index = int(raw_input('chose one'))
# init the class
my_class = load_class(food_list[food_index], subfood_list[food_index, subfood_index])
# the rest of the code
这只是为了简化,实际上,我打算通过获取目录自动填充food_list和subfood_list。
假设您有一个数据分类框架,并且想让用户选择他们想要使用的方法。用户还应该能够通过简单地添加 python 包和模块来扩展框架。
我希望这个例子是合理的。
再次编辑 接受的答案没有解决智能感知问题。但它展示了如何更好地编码。我认为这是IDE问题而不是python问题。我会发布另一个问题。
请您参考如下方法:
你想要使用 __import__ 内置函数:
def load_class(package, mod_name, cls_name):
mod = __import__('.'.join((package, mod_name)))
return getattr(mod, cls_name)
当然,如果您愿意,您可以将错误处理放回原处,老实说,我不太确定为什么您首先要这样做。对于大多数 事情,动态导入对我来说似乎是一种“代码味道”。请在开始使用之前评估您是否真的需要它。
