Pregunta

El siguiente código

import types
class A:
    class D:
        pass
    class C:
        pass
for d in dir(A):
    if type(eval('A.'+d)) is types.ClassType:
        print d

salidas

C
D

¿Cómo consigo que salga en el orden en que se definieron estas clases en el código? Es decir,

D
C

¿Hay alguna otra forma que no sea usar inspect.getsource (A) y analizar eso?

¿Fue útil?

Solución

El módulo inspeccionar también tiene la función findource . Devuelve una tupla de líneas de origen y número de línea donde se define el objeto.

>>> import inspect
>>> import StringIO
>>> inspect.findsource(StringIO.StringIO)[1]
41
>>>

La función findource realmente busca a través del archivo fuente y busca posibles candidatos si se le da un objeto de clase.

Dado un método, función, rastreo, marco u objeto de código, simplemente mira el atributo co_firstlineno del objeto de código (contenido).

Otros consejos

Tenga en cuenta que el análisis ya está hecho para usted en la inspección: eche un vistazo a inspect.findsource , que busca en el módulo la definición de clase y devuelve el origen y el número de línea. Ordenar por ese número de línea (también puede necesitar dividir las clases definidas en módulos separados) debería dar el orden correcto.

Sin embargo, esta función no parece estar documentada, y solo está usando una expresión regular para encontrar la línea, por lo que puede no ser demasiado confiable.

Otra opción es usar metaclases, o alguna otra forma de ordenar información implícita o explícitamente al objeto. Por ejemplo:

import itertools, operator

next_id = itertools.count().next

class OrderedMeta(type):
    def __init__(cls, name, bases, dct):
        super(OrderedMeta, cls).__init__(name, bases, dct)
        cls._order = next_id()

# Set the default metaclass
__metaclass__ = OrderedMeta

class A:
    class D:
        pass
    class C:
        pass

print sorted([cls for cls in [getattr(A, name) for name in dir(A)] 
           if isinstance(cls, OrderedMeta)], key=operator.attrgetter("_order"))

Sin embargo, este es un cambio bastante intrusivo (requiere establecer la metaclase de cualquier clase que le interese en OrderedMeta)

No, no puede obtener esos atributos en el orden que está buscando. Los atributos de Python se almacenan en un dict (léase: hashmap), que no tiene conocimiento del orden de inserción.

Además, evitaría el uso de eval simplemente diciendo

if type(getattr(A, d)) is types.ClassType:
    print d

en tu bucle. Tenga en cuenta que también puede iterar a través de pares clave / valor en A.__dict__

AFAIK, no, no hay *. Esto se debe a que todos los atributos de una clase se almacenan en un diccionario (que, como saben, no está ordenado).

*: en realidad podría ser posible, pero eso requeriría decoradores o posiblemente pirateo de metaclases. ¿Alguno de esos te interesa?

No estoy tratando de ser simplista aquí, pero ¿sería factible organizar las clases en su fuente alfabéticamente? Me parece que cuando hay muchas clases en un archivo, esto puede ser útil por derecho propio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top