Domanda

Il seguente codice

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

uscite

C
D

Come posso ottenere l'output nell'ordine in cui queste classi sono state definite nel codice? Cioè.

D
C

Esiste altro che usare inspect.getsource (A) e analizzarlo?

È stato utile?

Soluzione

Il modulo inspect ha anche la funzione foundource . Restituisce una tupla di righe di origine e numero di riga in cui l'oggetto è definito.

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

La funzione findource cerca effettivamente attraverso il file sorgente e cerca probabili candidati se gli viene assegnato un oggetto di classe.

Dato un metodo, una funzione, un traceback, un frame o un oggetto codice, guarda semplicemente l'attributo co_firstlineno dell'oggetto (contenuto) codice.

Altri suggerimenti

Nota che l'analisi è già stata eseguita per te in inspect - dai un'occhiata a inspect.findsource , che cerca il modulo per la definizione della classe e restituisce l'origine e il numero di riga. L'ordinamento per quel numero di riga (potrebbe anche essere necessario suddividere le classi definite in moduli separati) dovrebbe dare il giusto ordine.

Tuttavia, questa funzione non sembra essere documentata e sta semplicemente usando un'espressione regolare per trovare la linea, quindi potrebbe non essere troppo affidabile.

Un'altra opzione è quella di utilizzare metaclass, o in qualche altro modo di ordinare in modo implicito o esplicito informazioni sull'oggetto. Ad esempio:

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"))

Tuttavia, si tratta di una modifica piuttosto invadente (richiede l'impostazione della metaclasse di tutte le classi che ti interessano in OrderedMeta)

No, non puoi ottenere quegli attributi nell'ordine che stai cercando. Gli attributi Python sono memorizzati in un dict (leggi: hashmap), che non ha consapevolezza dell'ordine di inserimento.

Inoltre, eviterei l'uso di eval semplicemente dicendo

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

nel tuo loop. Nota che puoi anche scorrere tra coppie chiave / valore in A.__dict__

AFAIK, no - non c'è *. Questo perché tutti gli attributi di una classe sono memorizzati in un dizionario (che, come sai, non è ordinato).

*: potrebbe effettivamente essere possibile, ma ciò richiederebbe decoratori o possibilmente l'hacking della metaclasse. Uno di questi ti interessa?

Non sto provando a essere glib qui, ma sarebbe possibile per te organizzare le lezioni nella tua fonte in ordine alfabetico? trovo che quando ci sono molte classi in un file questo può essere utile a sé stante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top