2010-04-20 5 views
140

Existe-t-il un moyen de récupérer une liste d'attributs qui existent sur les instances d'une classe?Liste des attributs d'un objet

class new_class(): 
    def __init__(self, number): 
     self.multi = int(number) * 2 
     self.str = str(number) 

a = new_class(2) 
print(', '.join(a.SOMETHING)) 

Le résultat souhaité est que "multi, str" sera généré. Je veux que ceci voit les attributs courants des différentes parties d'un script.

+26

Presque tout le monde dans les noms Python leurs classes comme 'NewClass'. Vous pouvez défier les attentes des gens si vous utilisez une convention de dénomination comme 'new_class'. –

+0

Même s'il est interactif pour l'homme et ne peut pas être utilisé par programmation, la fonction 'help()' aide à obtenir des informations sur les classes, fonctions, builtins, modules et plus encore. – ytpillai

+0

Relevant: http://stackoverflow.com/questions/1398022/ looping-over-all-member-variables-of-a-class-in-python –

Répondre

18
>>> ', '.join(i for i in dir(a) if not i.startswith('__')) 
'multi, str' 

Ceci bien sûr imprimera n'importe quelles méthodes ou attributs dans la définition de classe. Vous pouvez exclure les méthodes « privées » en changeant i.startwith('__') à i.startwith('_')

161
>>> class new_class(): 
... def __init__(self, number): 
...  self.multi = int(number) * 2 
...  self.str = str(number) 
... 
>>> a = new_class(2) 
>>> a.__dict__ 
{'multi': 4, 'str': '2'} 
>>> a.__dict__.keys() 
dict_keys(['multi', 'str']) 

Vous pouvez également trouver pprint utile.

+15

Le problème de l'utilisation de __dict__ est apparu sur r/python. Quelqu'un a fait remarquer que vars (a) est équivalent à un .__ dict__ – David

+5

Au cas où quelqu'un se poserait la question, cela fonctionne également sur Python 2.7. –

+3

Pour être précis, 'pprint.pprint (a .__ dict __)' fait un joli print sur le les attributs. – smci

7

Que voulez-vous? Il peut être difficile de vous obtenir la meilleure réponse sans connaître votre intention exacte.

  • Il est presque toujours préférable de le faire manuellement si vous souhaitez afficher une instance de votre classe d'une manière spécifique. Cela inclura exactement ce que vous voulez et ne comprendra pas ce que vous ne voulez pas, et la commande sera prévisible.

    Si vous cherchez un moyen d'afficher le contenu d'une classe, formatez manuellement les attributs qui vous intéressent et fournissez-le comme méthode __str__ ou __repr__ pour votre classe.

  • Si vous souhaitez connaître les méthodes et les méthodes permettant de comprendre le fonctionnement d'un objet, utilisez help. help(a) vous montrera une sortie formatée sur la classe de l'objet en fonction de ses docstrings.

  • dir existe pour obtenir par programme tous les attributs d'un objet. (Accéder à __dict__ fait quelque chose que je regrouperais pareil mais que je ne m'utiliserais pas moi-même.) Cependant, cela peut ne pas inclure les choses que vous voulez et cela peut inclure des choses que vous ne voulez pas. Ce n'est pas fiable et les gens pensent qu'ils le veulent beaucoup plus souvent qu'eux. Sur une note quelque peu orthogonale, il existe très peu de support pour Python 3 à l'heure actuelle. Si vous êtes intéressé par l'écriture de vrais logiciels, vous allez vouloir des trucs de tierce partie comme numpy, lxml, Twisted, PIL, ou n'importe quel nombre de frameworks web qui ne supportent pas encore Python 3 et qui n'ont pas de plans trop tôt. Les différences entre la branche 2.6 et la branche 3.x sont faibles, mais la différence de support de bibliothèque est énorme.

+2

Je voudrais juste souligner que cinq ans plus tard (maintenant), je crois que tous les modules tiers que vous mentionnez supportent python3. Source: https://python3wos.appspot.com/ – pzkpfw

90
dir(instance) 
# or 
instance.__dict__ 

Ensuite, vous pouvez tester ce type est avec type() ou si est une méthode avec callable().

+2

'callable' n'existe pas dans py3k – SilentGhost

+3

(Et ne devrait probablement pas être utilisé dans Python 2.) –

+0

dir fonctionne mieux sur les classes avec l'attribut surchargé get/set – ogurets

38

vars(obj) Renvoie les attributs d'un objet.

+6

Ne fonctionne que pour les attributs __dict__. –

6

Il y a plus d'une façon de le faire:

#! /usr/bin/env python3 
# 
# This demonstrates how to pick the attiributes of an object 

class C(object) : 

    def __init__ (self, name="q"): 
    self.q = name 
    self.m = "y?" 

c = C() 

print (dir(c)) 

Lors de l'exécution, ce code produit:

[email protected]:~/skyset$ python3 attributes.py 
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',  '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm', 'q'] 

[email protected]:~/skyset$ 
+2

Pourquoi cette réponse a été downrowée? À des fins de débogage, dir fonctionne plutôt bien! – Dunatotatos

+0

Pretty fonctionne avec Python 2.7.x.Exactement ce que je voulais. –

0
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()] 
+0

Il ne fonctionne pas avec les noms d'attribut de classe commençant par une lettre majuscule ou un trait de soulignement simple. – fviktor

7

Il est souvent mentionné que la liste d'une liste complète des attributs devrait utiliser dir(). Notez cependant que contrairement à la croyance populaire dir() ne fait ressortir tous les attributs. Par exemple, vous pouvez remarquer que __name__ est peut-être manquant dans la liste dir() d'une classe même si vous pouvez y accéder depuis la classe elle-même. A partir de la doc sur dir() (Python 2, Python 3):

Comme est fourni dir() principalement à titre de commodité pour une utilisation à une invite interactive, il tente de fournir un ensemble intéressant de noms plus qu'il essaie de fournir un ensemble de noms rigoureusement ou uniformément défini , et son comportement détaillé peut changer d'une publication à l'autre. Par exemple , les attributs de métaclasse ne sont pas dans la liste de résultats lorsque l'argument est une classe.

Une fonction comme celle-ci tend à être plus complète, bien qu'il n'y ait aucune garantie d'exhaustivité puisque la liste renvoyée par dir() peut être affectée par de nombreux facteurs, notamment la mise en œuvre de la méthode __dir__(), ou la personnalisation __getattr__() ou __getattribute__() sur la classe ou un de ses parents. Voir les liens fournis pour plus de détails.

def dirmore(instance): 
    visible = dir(instance) 
    visible += [a for a in set(dir(type)).difference(visible) 
       if hasattr(instance, a)] 
    return sorted(visible) 
0

S'il vous plaît voir l'exécution de scripts shell Python suivant dans l'ordre, il donnera la solution de création de classe pour extraire les noms de champs de cas.

>>> class Details: 
...  def __init__(self,name,age): 
...   self.name=name 
...   self.age =age 
...  def show_details(self): 
...   if self.name: 
...    print "Name : ",self.name 
...   else: 
...    print "Name : ","_" 
...   if self.age: 
...    if self.age>0: 
...     print "Age : ",self.age 
...    else: 
...     print "Age can't be -ve" 
...   else: 
...    print "Age : ","_" 
... 
>>> my_details = Details("Rishikesh",24) 
>>> 
>>> print my_details 
<__main__.Details instance at 0x10e2e77e8> 
>>> 
>>> print my_details.name 
Rishikesh 
>>> print my_details.age 
24 
>>> 
>>> my_details.show_details() 
Name : Rishikesh 
Age : 24 
>>> 
>>> person1 = Details("",34) 
>>> person1.name 
'' 
>>> person1.age 
34 
>>> person1.show_details 
<bound method Details.show_details of <__main__.Details instance at 0x10e2e7758>> 
>>> 
>>> person1.show_details() 
Name : _ 
Age : 34 
>>> 
>>> person2 = Details("Rob Pike",0) 
>>> person2.name 
'Rob Pike' 
>>> 
>>> person2.age 
0 
>>> 
>>> person2.show_details() 
Name : Rob Pike 
Age : _ 
>>> 
>>> person3 = Details("Rob Pike",-45) 
>>> 
>>> person3.name 
'Rob Pike' 
>>> 
>>> person3.age 
-45 
>>> 
>>> person3.show_details() 
Name : Rob Pike 
Age can't be -ve 
>>> 
>>> person3.__dict__ 
{'age': -45, 'name': 'Rob Pike'} 
>>> 
>>> person3.__dict__.keys() 
['age', 'name'] 
>>> 
>>> person3.__dict__.values() 
[-45, 'Rob Pike'] 
>>> 
+0

Nous pouvons également vérifier la callablilty de chaque attributs.visit http://stackoverflow.com/questions/1398022/looping-over-all-member-variables-of-a-class-in-python?noredirect=1&lq=1 –

0

Comme il est écrit avant d'utiliser obj.__dict__ peut traiter les cas courants, mais certaines classes n'ont pas l'attribut __dict__ et utiliser __slots__ (la plupart du temps pour l'efficacité de la mémoire).

exemple d'une manière plus élastique de le faire:

class A(object): 
    __slots__ = ('x', 'y',) 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 


class B(object): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 


def get_object_attrs(obj): 
    try: 
     return obj.__dict__ 
    except AttributeError: 
     return {attr: getattr(obj, attr) for attr in obj.__slots__} 


a = A(1,2) 
b = B(1,2) 
assert not hasattr(a, '__dict__') 

print(get_object_attrs(a)) 
print(get_object_attrs(b)) 

la sortie de ce code:

{'x': 1, 'y': 2} 
{'x': 1, 'y': 2} 

Note1:
Python est un langage dynamique et il est toujours préférable de connaître les classes vous essayez d'obtenir les attributs car même ce code peut manquer certains cas.

Note2:
ce code ne sorties variables d'instance qui signifie variables de classe ne sont pas fournis.par exemple:

class A(object): 
    url = 'http://stackoverflow.com' 
    def __init__(self, path): 
     self.path = path 

print(A('/questions').__dict__) 

sorties de code:

{'path': '/questions'} 

Ce code n'imprime pas l'attribut de classe url et peut omettre les attributs recherchés de classe.
Parfois, nous pourrions penser qu'un attribut est un membre d'instance mais il n'est pas et ne sera pas montré en utilisant cet exemple.

11

Le module inspect fournit des moyens faciles pour inspecter un objet:

Le inspectent module fournit plusieurs fonctions utiles pour aider à obtenir informations sur les objets en direct tels que les modules, les classes, méthodes, fonctions, retraçage, cadre objets et objets de code.


En utilisant getmembers() vous pouvez voir tous les attributs de votre classe, ainsi que leur valeur. Pour exclure des attributs privés ou protégés, utilisez .startswith('_'). Pour exclure des méthodes ou des fonctions, utilisez inspect.ismethod() ou inspect.isfunction().

import inspect 


class NewClass(object): 
    def __init__(self, number): 
     self.multi = int(number) * 2 
     self.str = str(number) 

    def func_1(self): 
     pass 


a = NewClass(2) 

for i in inspect.getmembers(a): 
    # Ignores anything starting with underscore 
    # (that is, private and protected attributes) 
    if not i[0].startswith('_'): 
     # Ignores methods 
     if not inspect.ismethod(i[1]): 
      print(i) 

Notez que ismethod() est utilisé sur le deuxième élément de i depuis la première est simplement une chaîne (son nom). Hors service: utiliser CamelCase pour les noms de classe.

4

Veuillez voir le script shell python qui a été exécuté en séquence, ici vous obtiendrez les attributs d'une classe au format chaîne séparés par une virgule.

>>> class new_class(): 
...  def __init__(self, number): 
...   self.multi = int(number)*2 
...   self.str = str(number) 
... 
>>> a = new_class(4) 
>>> ",".join(a.__dict__.keys()) 
'str,multi'<br/> 

J'utilise python 3.4

+0

Et si vous voulez seulement la liste peut utiliser juste 'a .__ dict __. Keys()'. Cependant, si vous voulez savoir si un objet a un attribut spécifique, vous pouvez utiliser ['hasattr'] (http://stackoverflow.com/questions/610883/how-to-know-if-an-object-has-an- attribute-in-python). – berna1111

Questions connexes