Хорошо, это немного сложно.Сделайте динамический импорт, который все еще явственен в Python
Скажем, у меня есть модуль внутри упаковки:
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) не понимает мой код, и не может сделать IntelliSense (автоматическое завершение кода).
Если я использую первый подход, то IntelliSense, очевидно, работает:
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
Но если я использую второй подход, то IntelliSense не может сделать завершение для меня:
load_class('a_package', 'a_module', 'A_Class')(). # when I press ".", nothing happened
Я знаю, , это компромисс между динамическим импортом в Python. Но я хочу знать, есть ли какая-то альтернатива, позволяющая мне сделать второй подход (возможно, не использовать exec
), который все еще может позволить intellisense общей IDE (например, Pydev) угадывать метод внутри класса?
EDIT: Зачем мне это нужно? Скажем, у меня есть такая структура каталогов
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 к модулю.
Надеюсь, этот пример является разумным.
изменить еще раз принятый ответ не решает проблему intellisense. Но он показывает, как лучше кодировать. Я думаю, что это проблема IDE, а не проблема python. Я отправлю еще один вопрос.
Как ваш метод лучше, чем делать 'из package.module import klass'? Последнее гораздо более семантическое и не путает других программистов, которые смотрят на ваш код. –
Как я уже сказал, мой подход легче писать. Это также позволяет мне называть разные методы и классы с помощью переменной конфигурации. – goFrendiAsgard
Не пытайтесь быть умными. – hop