2008-10-10 17 views
184
dir(re.compile(pattern)) 

no devuelve el patrón como uno de los elementos de la lista. Es decir, que devuelve:¿Cómo obtener una lista completa de los métodos y atributos del objeto?

['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn'] 

Según el manual, se supone que contienen

the object's attributes' names, the names of its class's attributes, and recursively of the attributes of its class's base classes.

Se dice también que

The list is not necessarily complete.

¿Hay una manera de conseguir la completa lista ? Siempre asumí que dir devuelve una lista completa pero aparentemente no ...

También: ¿hay alguna manera de enumerar solo atributos? ¿O solo métodos?

Editar: esto es en realidad un error en Python -> supuestamente se fija en la rama 3.0 (y quizás también en 2,6)

+4

usando 'dir()' o el módulo de inspección es generalmente el camino correcto para hacerlo. ¿Usó el módulo 're' solo como ejemplo o quiere lograr un objetivo especial? – hop

+1

¿Está seguro de que el patrón se mantiene como datos una vez compilados? Tenía la impresión de que el objetivo de compilar un patrón era producir los autómatas de estados finitos necesarios para analizar el patrón dado. –

+0

@hop no puede ser eludido por las clases? Por ejemplo, pueden hacer su en '__dir __()' – ytpillai

Respuesta

118

Para la lista completa de atributos, la respuesta corta es: no. El problema es que los atributos se definen realmente como los argumentos aceptados por la función incorporada getattr. Como el usuario puede volver a implementar __getattr__, permitiendo de repente cualquier clase de atributo, no hay una forma genérica posible de generar esa lista. La función dir devuelve las claves en el atributo __dict__, es decir, todos los atributos accesibles si el método __getattr__ no se vuelve a implementar.

Para la segunda pregunta, realmente no tiene sentido. En realidad, los métodos son atributos que se pueden llamar, nada más. Sin embargo, podría filtrar los atributos que se pueden llamar y, mediante el módulo inspect, determinar los métodos, métodos o funciones de la clase.

+0

inpect.getmembers (re. compile (pattern)) tampoco genera un patrón como miembro, por lo que probablemente usa el directorio internamente ... ¡Esto apesta! –

+0

También podría usar invocable para comprobar si son métodos, pero ese no es el punto ... El punto es que no puedo confiar en que dir devuelva incluso la lista de atributos que son realmente visibles públicamente ... –

+2

inspeccionar está destinado a ser "al menos tan" confiable como dir(). Por otro lado, re es un módulo muy complicado – hop

48

Es por ello que el nuevo método __dir__() se ha añadido en Python 2.6

véase:

+0

consigo este error: >> __dir __ (pyrenderdoc) Rastreo (llamada más reciente pasado): Archivo "", línea 1, en NameError: nombre '__dir__' no está definido –

+0

'__dir' __ () es un método sobre objeto, no una función - por favor lea los enlaces en la respuesta y [esto] (https://docs.python.org/3/reference/datamodel.html#object.__dir__) – Moe

18

Aquí es una práctica además de las respuestas de PierreBdR y Moe:

- para Python> = 2.6 y las clases de nuevo estilo, dir() parece ser suficiente;
- para las clases de estilo antiguo, al menos podemos hacer lo que un standard module hace para apoyar la implementación del tabulador: además de dir(), busque __class__ - y luego ir por su __bases__:

# code borrowed from the rlcompleter module 
# tested under Python 2.6 (sys.version = '2.6.5 (r265:79063, Apr 16 2010, 13:09:56) \n[GCC 4.4.3]') 

# or: from rlcompleter import get_class_members 
def get_class_members(klass): 
    ret = dir(klass) 
    if hasattr(klass,'__bases__'): 
     for base in klass.__bases__: 
      ret = ret + get_class_members(base) 
    return ret 


def uniq(seq): 
    """ the 'set()' way (use dict when there's no set) """ 
    return list(set(seq)) 


def get_object_attrs(obj): 
    # code borrowed from the rlcompleter module (see the code for Completer::attr_matches()) 
    ret = dir(obj) 
    ## if "__builtins__" in ret: 
    ## ret.remove("__builtins__") 

    if hasattr(obj, '__class__'): 
     ret.append('__class__') 
     ret.extend(get_class_members(obj.__class__)) 

     ret = uniq(ret) 

    return ret 

(El código de prueba y la salida se eliminan por brevedad, pero básicamente para objetos de estilo nuevo parecemos tener los mismos resultados para get_object_attrs() que para dir(), y para las clases antiguas la principal adición a la salida dir() parece ser el atributo __class__))

1

Ésta es la forma en que lo hice, útil sólo para los objetos personalizados simples a los que mantienen los atributos añadiendo: Dado un objeto obj creada con obj = type("CustomObj",(object,),{}), o simplemente:

class CustomObj(object): 
    pass 
obj=CustomObject() 

a continuación, para obtener un diccionario con solo los atributos personalizados, lo que hago es:

{key: value for key, value in self.__dict__.items() if not key.startswith("__")} 
Cuestiones relacionadas