2011-08-04 29 views
66

¿Cómo obtengo el nombre de la clase en la que me encuentro actualmente?¿Obtener el nombre de la clase actual?

Ejemplo:

def get_input(class_name): 
    [do things] 
    return class_name_result 

class foo(): 
    input = get_input([class name goes here]) 

Debido a la naturaleza del programa que estoy de interfaz con (vistrails), no puedo utilizar __init__() para inicializar input.

Respuesta

18

Dentro del cuerpo de una clase, el nombre de la clase aún no está definido, por lo que no está disponible. ¿No puedes simplemente escribir el nombre de la clase? Tal vez deba decir más sobre el problema para que podamos encontrar una solución para usted.

Crearía una metaclase para hacer este trabajo por usted. Se invoca en el momento de creación de clase (conceptualmente al final de la clase: bloque) y puede manipular la clase que se está creando. No he probado esto:

class InputAssigningMetaclass(type): 
    def __new__(cls, name, bases, attrs): 
     cls.input = get_input(name) 
     return super(MyType, cls).__new__(cls, name, bases, newattrs) 

class MyBaseFoo(object): 
    __metaclass__ = InputAssigningMetaclass 

class foo(MyBaseFoo): 
    # etc, no need to create 'input' 

class foo2(MyBaseFoo): 
    # etc, no need to create 'input' 
+0

para aclarar lo que estoy tratando de hacer: necesito crear e inicializar una variable de clase, 'entrada', ** exterior de un método **. Tengo un montón de clases pequeñas, cada una de las cuales debe llamar a 'get_input' usando su nombre de clase como parámetro. Intento generalizar esto para no tener que ir a cada clase (habrá 100 o más) y escribir el nombre de la clase. –

+0

OK, he actualizado mi respuesta con una metaclase que debería ayudar. –

+0

¿A qué se refiere 'MyType' en la línea' super' en 'InputAssigningMetaclass'? –

12

puede acceder a él por la clase atributos particulares:

cls_name = self.__class__.__name__ 

EDIT:

Según lo dicho por Ned Batcheler, esto no funcionaría en el cuerpo de la clase, pero lo haría en un método.

99

obj.__class__.__name__ le conseguirá cualquier nombre de los objetos, por lo que se puede hacer esto:

class Clazz(): 
    def getName(self): 
     return self.__class__.__name__ 

Uso:

>>> c = Clazz() 
>>> c.getName() 
'Clazz' 
+0

¿Por qué no es esta la respuesta aceptada? EDITAR: Ok, el alcance de OP no es interno, está a nivel de clase. – KomodoDave

+1

@KomodoDave, porque esto es incorrecto, incluso en el alcance del método. Cuando llame a 'getName' desde una clase secundaria, dará como resultado el nombre de la clase secundaria. Entonces se vuelve complicado si REALMENTE desea la clase con la que está trabajando. –

+0

@KenetJervet ¿Quieres decir que cuando llamas a 'getName' de una clase _parent_ dará como resultado el nombre de la clase secundaria? Ok ty para señalar eso. – KomodoDave

7

EDIT: Sí, puede; pero tiene que hacer trampa: el nombre de la clase que se está ejecutando actualmente está presente en la pila de llamadas, y el módulo traceback le permite acceder a la pila.

>>> import traceback 
>>> def get_input(class_name): 
...  return class_name.encode('rot13') 
... 
>>> class foo(object): 
...  _name = traceback.extract_stack()[-1][2] 
...  input = get_input(_name) 
... 
>>> 
>>> foo.input 
'sbb' 

Sin embargo, yo no haría esto; Mi respuesta original sigue siendo mi propia preferencia como solución. Respuesta original:

probablemente la solución más simple es utilizar un decorador, que es similar a la respuesta de Ned que implica metaclases, pero menos potente (decoradores son capaces de magia negro, pero metaclases son capaces de antigua, oculto magia negro)

>>> def get_input(class_name): 
...  return class_name.encode('rot13') 
... 
>>> def inputize(cls): 
...  cls.input = get_input(cls.__name__) 
...  return cls 
... 
>>> @inputize 
... class foo(object): 
...  pass 
... 
>>> foo.input 
'sbb' 
>>> 
1
import sys 

def class_meta(frame): 
    class_context = '__module__' in frame.f_locals 
    assert class_context, 'Frame is not a class context' 

    module_name = frame.f_locals['__module__'] 
    class_name = frame.f_code.co_name 
    return module_name, class_name 

def print_class_path(): 
    print('%s.%s' % class_meta(sys._getframe(1))) 

class MyClass(object): 
    print_class_path() 
Cuestiones relacionadas