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

ne renvoie pas de modèle comme l'un des éléments de la liste. A savoir, il retourne:Comment obtenir une liste complète des méthodes et des attributs de l'objet?

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

Selon le manuel, il est censé contenir

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

Il dit aussi que

The list is not necessarily complete.

Y at-il un moyen d'obtenir la complète liste ? J'ai toujours supposé que dir renvoie une liste complète, mais apparemment il ne le fait pas ...

En outre: est-il un moyen de lister uniquement les attributs? Ou seulement des méthodes?

Edit: c'est en fait un bug en python -> soi-disant il est fixé dans la branche 3.0 (et peut-être aussi à 2,6)

+4

en utilisant 'dir()' ou le module d'inspection est généralement la bonne façon de le faire. Avez-vous utilisé le module 're' comme exemple ou voulez-vous atteindre un objectif particulier? – hop

+1

Etes-vous sûr que le modèle est réellement conservé en tant que données une fois compilées? J'avais l'impression que le but de compiler un motif était de produire les automates à états finis nécessaires pour analyser le motif donné. –

+0

@hop ne peut pas être contourné par des classes? Par exemple, ils peuvent faire leur '__dir __() ' – ytpillai

Répondre

118

Pour la complète liste des attributs, la réponse courte est: non. Le problème est que les attributs sont réellement définis comme les arguments acceptés par la fonction intégrée getattr. Comme l'utilisateur peut réimplémenter __getattr__, permettant soudainement n'importe quel type d'attribut, il n'y a aucun moyen générique possible de générer cette liste. La fonction dir renvoie les clés de l'attribut __dict__, c'est-à-dire tous les attributs accessibles si la méthode __getattr__ n'est pas réimplémentée.

Pour la deuxième question, cela n'a pas vraiment de sens. En fait, les méthodes sont des attributs appelables, rien de plus. Vous pouvez cependant filtrer les attributs appelables et, à l'aide du module inspect, déterminer les méthodes, méthodes ou fonctions de classe.

+0

inpect.getmembers (re. compile (pattern)) ne donne pas non plus de pattern en tant que membre, donc il utilise probablement dir en interne ... C'est nul! –

+0

Je pourrais aussi utiliser callable pour vérifier si elles sont des méthodes, mais ce n'est pas le point ... Le point est que je ne peux pas croire dir pour retourner même la liste des attributs qui sont réellement visibles publiquement ... –

+2

inspecter est censé être "au moins aussi" digne de confiance que dir(). D'autre part, re est un module très compliqué – hop

48

C'est la raison pour laquelle la nouvelle méthode __dir__() a été ajouté en python 2.6

voir:

+0

Je reçois cette erreur: >> __dir __ (pyrenderdoc) retraçage (le plus récent appel dernier): Fichier "", ligne 1, en NameError: nom '__dir__' est pas défini –

+0

'__dir' __ () est une méthode sur l'objet, pas une fonction - s'il vous plaît lire les liens dans la réponse et [ceci] (https://docs.python.org/3/reference/datamodel.html#object.__dir__) – Moe

18

Voici une ajout pratique aux réponses de PierreBdR et Moe:

- pour Python> = 2.6 et les classes de style nouveau, dir() semble être suffisant;
- pour les classes de style ancien, nous pouvons au moins faire ce qu'un standard module fait pour appuyer la touche de tabulation: en plus de dir(), chercher __class__ - puis d'aller pour son __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 

(Le code de test et la sortie sont supprimés par souci de brièveté, mais pour les objets de style nouveau, nous semblons avoir les mêmes résultats pour get_object_attrs() que pour dir(), et pour les classes de style ancien, l'ajout principal à la sortie dir() semble être l'attribut __class__))

1

Voilà comment je l'ai fait, utile que pour les objets personnalisés simples à qui vous gardez les attributs d'ajouter: donné un obj objet créé avec obj = type("CustomObj",(object,),{}), ou tout simplement:

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

puis, pour obtenir un dictionnaire avec seulement les attributs personnalisés, ce que je fais est:

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