Comment obtenir une liste complète des méthodes et attributs de l'objet?

230
dir(re.compile(pattern)) 

ne renvoie pas de motif comme l'un des éléments des listes. À savoir, il renvoie:

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

Selon le manuel, il est censé contenir

les noms des attributs de l'objet, les noms des attributs de sa classe et récursivement des attributs des classes de base de sa classe.

Il dit aussi que

La liste n'est pas nécessairement complète.

Existe-t-il un moyen d'obtenir la liste complète ? J'ai toujours supposé que dir renvoyait une liste complète mais apparemment ce n'est pas le cas ...

Aussi: existe-t-il un moyen de répertorier uniquement les attributs? Ou seulement des méthodes?

Edit: c'est en fait un bug en python -> soi-disant il est corrigé dans la branche 3.0 (et peut-être aussi en 2.6)

Bartosz Radaczyński
la source
5
l'utilisation dir()ou le module d'inspection est généralement la bonne façon de le faire. Avez-vous utilisé le remodule à titre d'exemple ou souhaitez-vous atteindre un objectif spécial?
1
Êtes-vous sûr que le modèle est réellement conservé sous forme de données une fois compilé? J'avais l'impression que le point de compilation d'un motif était de produire les automates à états finis nécessaires pour analyser le motif donné.
Kyle Strand
@hop ne peut pas être contourné par les classes? Par exemple, ils peuvent faire leur__dir__()
ytpillai
ytpillai: correct, mais seulement en Python 3. Même ainsi, la question est de savoir si une telle classe tomberait dans le "cas général"

Réponses:

140

Pour la liste complète 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 getattrfonction intégrée. Comme l'utilisateur peut réimplémenter __getattr__, autorisant soudainement tout type d'attribut, il n'existe aucun moyen générique possible de générer cette liste. La dirfonction renvoie les clés de l' __dict__attribut, c'est-à-dire tous les attributs accessibles si la __getattr__méthode 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 inspectmodule, déterminer les méthodes, méthodes ou fonctions de classe.

PierreBdR
la source
1
inpect.getmembers (re.compile (pattern)) ne donne pas non plus pattern en tant que membre, donc il utilise probablement dir en interne ... Cela craint!
Bartosz Radaczyński
Je pourrais également utiliser callable pour vérifier si ce sont des méthodes, mais ce n'est pas le point ... Le fait est que je ne peux pas faire confiance à dir pour retourner même la liste des attributs qui sont réellement visibles publiquement ...
Bartosz Radaczyński
2
inspect est censé être "au moins aussi" digne de confiance que dir (). d'un autre côté, re est un module très compliqué
Que définissez-vous par "visible publiquement"? Si vous voulez dire "peut être consulté", alors c'est une cause perdue pour la raison donnée. Sinon, 'dir' renvoie toujours la liste des attributs accessibles avec l'implémentation par défaut de getattr.
PierreBdR
2
dir (my_class) renvoie quelque chose de différent de my_class .__ dict __. keys (). l'ancien
affiche
58

C'est pourquoi la nouvelle __dir__()méthode a été ajoutée en python 2.6

voir:

Moe
la source
J'obtiens cette erreur: >> dir __ (pyrenderdoc) Traceback (dernier appel le plus récent): Fichier "<string>", ligne 1, dans <module> NameError: le nom '__dir ' n'est pas défini
Mona Jalal
__dir__ () est une méthode sur un objet, pas une fonction - veuillez lire les liens dans la réponse et ceci
Moe
Une ligne pour imprimer tous les attributs et leurs valeurs:pprint({k:getattr(ojb,k) for k in obj.__dir__()})
Czechnology
21

Voici un complément pratique aux réponses de PierreBdR et Moe:

  • Pour Python> = 2.6 et les classes de nouveau style , cela dir()semble suffisant.
  • Pour les classes à l'ancienne , nous pouvons au moins faire ce qu'un module standard fait pour prendre en charge la complétion des onglets: en plus de dir()rechercher __class__, puis de rechercher __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 concision, mais fondamentalement, pour les objets de nouveau style, nous semblons avoir les mêmes résultats get_object_attrs()que pour dir()et pour les classes de style ancien, l'ajout principal à la dir()sortie semble être l' __class__attribut.)

ジ ョ ー ジ
la source
9

Uniquement pour compléter:

  1. dir()est l' outil le plus puissant / fondamental. (Le plus recommandé )
  2. Des solutions autres que dir()simplement fournir leur façon de traiter la sortie dedir() .

    En listant les attributs de 2e niveau ou non, il est important de faire le filtrage par vous-même, car parfois vous voudrez peut-être filtrer les variables internes avec des soulignements __, mais parfois vous aurez peut-être besoin de la __doc__chaîne de doc.

  3. __dir__()et dir()renvoie un contenu identique.
  4. __dict__et dir()sont différents. __dict__renvoie un contenu incomplet.
  5. IMPORTANT : __dir__()peut parfois être écrasé par une fonction, une valeur ou un type, par l'auteur pour n'importe quel but.

    Voici un exemple:

    \\...\\torchfun.py in traverse(self, mod, search_attributes)
    445             if prefix in traversed_mod_names:
    446                 continue
    447             names = dir(m)
    448             for name in names:
    449                 obj = getattr(m,name)

    TypeError: le descripteur __dir__de l' 'object'objet a besoin d'un argument

    L'auteur de PyTorch a modifié la __dir__()méthode en quelque chose qui nécessite un argument. Cette modification dir()échoue.

  6. Si vous voulez qu'un schéma fiable traverse tous les attributs d'un objet, n'oubliez pas que chaque norme pythonique peut être remplacée et peut ne pas tenir , et chaque convention peut ne pas être fiable.

Chiron
la source
5

Voici comment je le fais, utile pour les objets personnalisés simples auxquels vous continuez d'ajouter des attributs:

Soit un objet créé avec obj = type("Obj",(object,),{}), ou simplement:

class Obj: pass
obj = Obj()

Ajoutez quelques attributs:

obj.name = 'gary'
obj.age = 32

puis, pour obtenir un dictionnaire avec uniquement les attributs personnalisés:

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

# {'name': 'gary', 'age': 32}
mluc
la source
liste de tous les attributs dans Python 3.x: {key: valeur pour key, valeur dans obj .__ dict __. items () sinon key.startswith ("__")} ['_
declare_fields