Eu preciso pegar um argumento de string e criar um objeto da classe nomeada nessa string em Python. Em Java, eu usaria Class.forName().newInstance()
. Existe um equivalente em Python?
Obrigado pelas respostas. Para responder a quem quer saber o que estou fazendo: quero usar um argumento de linha de comando como o nome da classe e instanciá-lo. Na verdade, estou programando em Jython e instanciando classes Java, daí o Java-ness da questão. getattr()
funciona bem. Muito obrigado.
java
python
class
instantiation
Jason
fonte
fonte
importlib.import
, que foi feito backport de python 3 para 2.7 ( docs.python.org/2/library/importlib.html )Respostas:
A reflexão em python é muito mais fácil e flexível do que em Java.
Eu recomendo a leitura deste tutorial
Não há nenhuma função direta (que eu saiba) que recebe um nome de classe totalmente qualificado e retorna a classe, no entanto, você tem todas as peças necessárias para construir isso e pode conectá-las.
Porém, um conselho: não tente programar no estilo Java quando estiver em python.
Se você puder explicar o que está tentando fazer, talvez possamos ajudá-lo a encontrar uma maneira mais pítônica de fazer isso.
Esta é uma função que faz o que você deseja:
Você pode usar o valor de retorno desta função como se fosse a própria classe.
Aqui está um exemplo de uso:
Como isso funciona?
Estamos usando
__import__
para importar o módulo que contém a classe, o que exigiu que primeiro extraíssemos o nome do módulo do nome totalmente qualificado. Em seguida, importamos o módulo:Nesse caso,
m
se referirá apenas ao módulo de nível superior,Por exemplo, se sua classe reside em um
foo.baz
módulo, entãom
será o módulo.foo
Podemos facilmente obter uma referência ao
foo.baz
usogetattr( m, 'baz' )
Para ir do módulo de nível superior para a classe, deve-se usar recursivamente
gettatr
nas partes do nome da classeDigamos, por exemplo, se o nome da sua classe é,
foo.baz.bar.Model
então fazemos o seguinte:Isso é o que está acontecendo neste loop:
No final do loop,
m
haverá uma referência para a aula. Isso significa quem
na verdade é a própria classe, você pode fazer, por exemplo:fonte
__import__
existe. Projetos como o Django que fazem magia de carregamento de módulo o usam o tempo todo. Boa resposta.get_class = lambda name: reduce(getattr, name.split('.')[1:], __import__(name.partition('.')[0]))
. Embora 'object.from_name' possa ser um nome melhor. Exemplos: get_class ('decimal.Decimal'), get_class (module_name).Supondo que a classe esteja em seu escopo:
De outra forma:
Edit: Note, você não pode dar um nome como 'foo.bar' para getattr. Você precisará dividir por. e chame getattr () em cada peça da esquerda para a direita. Isso vai lidar com isso:
fonte
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))
Uso
fonte
Mais uma implementação.
fonte
if module_name
LBYL é bastante redundantes, uma vez que o erro que você ganha se você simplesmente apagar essas linhas é:ValueError: Empty module name
.Parece que você está abordando isso pelo meio em vez do começo. O que você realmente está tentando fazer? Encontrar a classe associada a uma determinada string é um meio para um fim.
Se você esclarecer seu problema, o que pode exigir sua própria refatoração mental, uma solução melhor pode se apresentar.
Por exemplo: Você está tentando carregar um objeto salvo com base em seu nome de tipo e um conjunto de parâmetros? Python soletra isso despickling e você deve olhar para o módulo pickle . E mesmo que o processo de remoção faça exatamente o que você descreve, você não precisa se preocupar com como ele funciona internamente:
fonte
Ele é encontrado na biblioteca padrão do python, como unittest.TestLoader.loadTestsFromName. Infelizmente, o método continua fazendo atividades adicionais relacionadas ao teste, mas este primeiro parece reutilizável. Eu editei para remover a funcionalidade relacionada ao teste:
fonte
Eu precisava obter objetos para todas as classes existentes em
my_package
. Então, eu importo todas as classes necessárias paramy_package
o de__init__.py
.Portanto, minha estrutura de diretório é assim:
E minha
__init__.py
aparência é assim:Então eu crio uma função como esta:
Onde
module_name = 'my_package'
inspecione o documento: https://docs.python.org/3/library/inspect.html#inspect.getmembers
fonte