Мне нужно взять строковый аргумент и создать объект класса, названного в этой строке, в Python. В Java я бы использовал Class.forName().newInstance()
. Есть ли эквивалент в Python?
Спасибо за ответы. Чтобы ответить тем, кто хочет знать, что я делаю: я хочу использовать аргумент командной строки в качестве имени класса и создать его экземпляр. На самом деле я программирую на Jython и создаю экземпляры классов Java, отсюда и Java-суть вопроса. getattr()
прекрасно работает. Большое спасибо.
java
python
class
instantiation
Джейсон
источник
источник
importlib.import
, который был перенесен с python 3 на 2.7 ( docs.python.org/2/library/importlib.html )Ответы:
Отражение в Python намного проще и гибче, чем в Java.
Я рекомендую прочитать этот урок
Нет прямой функции (о которой я знаю), которая принимает полное имя класса и возвращает класс, однако у вас есть все части, необходимые для его создания, и вы можете соединить их вместе.
Один небольшой совет: не пытайтесь программировать в стиле Java, когда вы работаете на Python.
Если вы сможете объяснить, что именно вы пытаетесь сделать, возможно, мы сможем помочь вам найти более питонический способ сделать это.
Вот функция, которая делает то, что вы хотите:
Вы можете использовать возвращаемое значение этой функции, как если бы это был сам класс.
Вот пример использования:
Как это работает?
Мы используем
__import__
для импорта модуля, содержащего класс, что требовало, чтобы мы сначала извлекли имя модуля из полного имени. Затем импортируем модуль:В этом случае
m
будет относиться только к модулю верхнего уровня,Например, если ваш класс живет в
foo.baz
модуле, тогдаm
это будет модуль.foo
Мы можем легко получить ссылку на
foo.baz
использованиеgetattr( m, 'baz' )
Чтобы перейти от модуля верхнего уровня к классу, необходимо рекурсивно использовать
gettatr
части имени классаСкажем, например, если ваше имя класса,
foo.baz.bar.Model
мы сделаем следующее:Вот что происходит в этом цикле:
В конце цикла
m
будет ссылка на класс. Это означает, чтоm
на самом деле это класс itslef, вы можете, например,:источник
__import__
для чего существует. Такие проекты, как Django, которые занимаются загрузкой модулей, используют его постоянно. Хороший ответ.get_class = lambda name: reduce(getattr, name.split('.')[1:], __import__(name.partition('.')[0]))
. Хотя имя object.from_name могло бы быть более подходящим. Примеры: get_class ('decimal.Decimal'), get_class (module_name).Предполагая, что класс находится в вашей области:
В противном случае:
Изменить: обратите внимание, вы не можете дать имя типа «foo.bar» для getattr. Вам нужно будет разделить его на. и вызовите getattr () для каждой части слева направо. Это справится с этим:
источник
attrs = 'foo.bar.baz'.split('.'); fooBar = reduce(getattr, attrs[1:], __import__(attrs[0]))
module, _, attrs = 'foo.bar.baz'.partition('.'); fooBar = reduce(getattr, attrs, __import__(module))
использование
источник
Еще одна реализация.
источник
if module_name
LBYL довольно redudant, так как ошибка , которую вы получите , если вы просто удалите эти строки является:ValueError: Empty module name
.Кажется, вы подходите к этому с середины, а не с начала. Что ты на самом деле пытаешься сделать? Поиск класса, связанного с данной строкой, является средством достижения цели.
Если вы проясните свою проблему, которая может потребовать вашего собственного мысленного рефакторинга, лучшее решение может появиться само собой.
Например: вы пытаетесь загрузить сохраненный объект на основе его имени типа и набора параметров? Python произносит это «unpickling», и вам стоит взглянуть на модуль pickle . И хотя процесс распаковки делает именно то, что вы описываете, вам не нужно беспокоиться о том, как он работает внутри:
источник
Он находится в стандартной библиотеке Python как unittest.TestLoader.loadTestsFromName. К сожалению, метод продолжает выполнять дополнительные действия, связанные с тестированием, но это первое ha выглядит пригодным для повторного использования. Я отредактировал его, чтобы удалить функции, связанные с тестами:
источник
Мне нужно было получить объекты для всех существующих классов в
my_package
. Так что я импортировать все необходимые классы вmy_package
«с__init__.py
.Итак, моя структура каталогов такая:
А мой
__init__.py
выглядит так:Затем я создаю такую функцию:
куда
module_name = 'my_package'
проверить документ: https://docs.python.org/3/library/inspect.html#inspect.getmembers
источник