Python имеет эквивалент Java Class.forName ()?

89
задан Erik Kaplun 28 September 2013 в 18:16
поделиться

5 ответов

Отражение в Python намного легче и намного более гибко, чем это находится в Java.

я рекомендую читать этот учебное руководство

, Там не прямая функция (что я знаю о), который берет полностью определенное имя класса и возвращает класс, однако у Вас есть все части, должен был создать это, и можно соединить их вместе.

Один совет, хотя: не пытайтесь программировать в стиле Java, когда Вы будете в Python.

, Если можно объяснить, что является им, что Вы пытаетесь сделать, возможно, мы можем помочь Вам найти больше pythonic способа сделать его.

Вот функция, которая делает то, что Вы хотите:

def get_class( kls ):
    parts = kls.split('.')
    module = ".".join(parts[:-1])
    m = __import__( module )
    for comp in parts[1:]:
        m = getattr(m, comp)            
    return m

можно использовать возвращаемое значение этой функции, как будто это был сам класс.

Вот пример использования:

>>> D = get_class("datetime.datetime")
>>> D
<type 'datetime.datetime'>
>>> D.now()
datetime.datetime(2009, 1, 17, 2, 15, 58, 883000)
>>> a = D( 2010, 4, 22 )
>>> a
datetime.datetime(2010, 4, 22, 0, 0)
>>> 

, Как это работает?

Мы используем __import__ для импорта модуля, который содержит класс, который потребовал, чтобы мы сначала извлекли имя модуля из полностью определенного имени. Тогда мы импортируем модуль:

m = __import__( module )

В этом случае, m будет только относиться к высокоуровневому модулю,

, Например, если Ваши жизни класса в foo.baz модуль, то m будет модуль foo
, Мы можем легко получить ссылку на [1 111], использование getattr( m, 'baz' )

, Чтобы добраться от высокоуровневого модуля до класса, иметь для рекурсивного использования gettatr на частях имени класса

Говорят, например, если Вы, которые имя класса foo.baz.bar.Model тогда, мы делаем это:

m = __import__( "foo.baz.bar" ) #m is package foo
m = getattr( m, "baz" ) #m is package baz
m = getattr( m, "bar" ) #m is module bar
m = getattr( m, "Model" ) #m is class Model

Это - то, что происходит в этом цикле:

for comp in parts[1:]:
    m = getattr(m, comp)    

В конце цикла, m будет ссылка на класс. Это означает, что m на самом деле сам класс, можно сделать, например:

a = m() #instantiate a new instance of the class    
b = m( arg1, arg2 ) # pass arguments to the constructor
160
ответ дан hasen 24 November 2019 в 07:15
поделиться

Принятие класса находится в Вашем объеме:

globals()['classname'](args, to, constructor)

Иначе:

getattr(someModule, 'classname')(args, to, constructor)

Редактирование: Отметьте, Вы не можете дать имя как 'foo.bar' к getattr. Необходимо будет разделить его. и назовите getattr () на каждой части слева направо. Это обработает это:

module, rest = 'foo.bar.baz'.split('.', 1)
fooBar = reduce(lambda a, b: getattr(a, b), rest.split('.'), globals()[module])
someVar = fooBar(args, to, constructor)
25
ответ дан Cody Brocious 24 November 2019 в 07:15
поделиться

Кажется приближением к этому с середины вместо начала. Что Вы действительно пытаетесь сделать? Нахождение класса, связанного с данной строкой, является средством для конца.

при разъяснении проблемы которая могла бы потребовать собственного умственного рефакторинга, лучшее решение может представить себя.

, Например: Вы пытаетесь загрузить сохраненное основанное на объектах на его имени типа и ряде параметров? Python записывает это несоление, и необходимо посмотреть модуль рассола . И даже при том, что процесс несоления делает точно, что Вы описываете, Вы не должны волноваться о том, как он работает внутренне:

>>> class A(object):
...   def __init__(self, v):
...     self.v = v
...   def __reduce__(self):
...     return (self.__class__, (self.v,))
>>> a = A("example")
>>> import pickle
>>> b = pickle.loads(pickle.dumps(a))
>>> a.v, b.v
('example', 'example')
>>> a is b
False
3
ответ дан 24 November 2019 в 07:15
поделиться

Я должен был получить объекты для всех существующих классов в my_package. Таким образом, я импортирую все необходимые классы в my_package __init__.py.

, Таким образом, моя структура каталогов похожа на это:

/my_package
    - __init__.py
    - module1.py
    - module2.py
    - module3.py

И мой __init__.py похож на это:

from .module1 import ClassA
from .module2 import ClassB

Затем я создаю функцию как это:

def get_classes_from_module_name(module_name):
    return [_cls() for _, _cls in inspect.getmembers(__import__(module_name), inspect.isclass)]

, Где module_name = 'my_package'

осматривают документ: https://docs.python.org/3/library/inspect.html#inspect.getmembers

0
ответ дан 24 November 2019 в 07:15
поделиться

Еще одна реализация.

def import_class(class_string):
    """Returns class object specified by a string.

    Args:
        class_string: The string representing a class.

    Raises:
        ValueError if module part of the class is not specified.
    """
    module_name, _, class_name = class_string.rpartition('.')
    if module_name == '':
        raise ValueError('Class name must contain module part.')
    return getattr(
        __import__(module_name, globals(), locals(), [class_name], -1),
        class_name)
4
ответ дан 24 November 2019 в 07:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: