Pergunta

O código a seguir

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

saídas

C
D

Como faço para obtê-lo para a saída na ordem em que essas classes foram definidas no código? I.

D
C

Existe alguma maneira à excepção de usar inspect.getsource (A) e analisar isso?

Foi útil?

Solução

O módulo inspect também tem a função findsource. Ele retorna um tuplo de linhas de código e número de linha, onde o objecto é definido.

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

A função findsource realmente pesquisas da calha do arquivo de origem e procura prováveis ??candidatos, se for dada uma classe-objeto.

Dada uma metodolo-, Função-, traceback-, enquadramento, ou código-objeto, ele simplesmente olha para o atributo co_firstlineno do (contida) de código-objeto.

Outras dicas

Note que que a análise já é feito para você em inspecionar - dê uma olhada inspect.findsource, que busca o módulo para a definição de classe e retorna o número de fonte e linha. A classificação em que o número da linha (você também pode precisar dividir a classes definidas em módulos separados) deve dar a ordem correta.

No entanto, esta função não parece ser documentadas, e está apenas usando uma expressão regular para encontrar a linha, por isso pode não ser muito confiável.

Outra opção é usar metaclasses, ou alguma outra forma de encomendar implícita ou explicitamente informações para o objeto. Por exemplo:

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

No entanto, esta é uma mudança bastante intrusiva (requer definindo o metaclass de quaisquer classes que você está interessado em OrderedMeta)

Não, você não pode obter esses atributos na ordem que você está procurando. atributos do Python são armazenados em um dicionário (leia-se: hashmap), que não tem consciência da ordem de inserção.

Além disso, gostaria de evitar o uso de eval, simplesmente dizendo

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

no seu loop. Note que você também pode simplesmente iterate através de pares chave / valor em A.__dict__

AFAIK, não - não há *. Isso ocorre porque todos os atributos de uma classe são armazenados em um dicionário (que é, como se sabe, não ordenada).

*: ele pode realmente ser possível, mas isso exigiria tanto decoradores ou possivelmente metaclass hacking. Fazer qualquer um daqueles que você interesse?

Eu não estou tentando ser glib aqui, mas seria viável para você organizar as classes em sua fonte em ordem alfabética? Acho que quando há muitas aulas em um arquivo que pode ser útil em seu próprio direito.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top