2010-04-20 9 views
140

¿Hay alguna forma de obtener una lista de atributos que existen en las instancias de una clase?Listar atributos de un objeto

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

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

El resultado deseado es que se generará "multi, str". Quiero que esto vea los atributos actuales de varias partes de un script.

+26

Prácticamente todo el mundo en los nombres de sus clases de Python como 'NewClass'. Puede desafiar las expectativas de las personas si usa una convención de nomenclatura como 'new_class'. –

+0

Aunque es humano-interactivo y no se puede utilizar de forma programática, la función 'help()' ayuda a obtener información sobre clases, funciones, builtins, módulos y más – ytpillai

+0

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

Respuesta

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

Esto, por supuesto, imprimirá cualquier método o atributo en la definición de la clase. Puede excluir métodos "privadas" cambiando i.startwith('__') a 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']) 

También puede encontrar pprint útil.

+15

El problema del uso de __dict__ acaba de aparecer en r/python. alguien señaló que vars (a) es equivalente a .__ dict__ – David

+5

En caso de que alguien se esté preguntando, esto también funciona en Python 2.7 –

+3

Para ser específico, 'pprint.pprint (a .__ dict __)' hace una bonita impresión en el atributos. – smci

7

¿Para qué quiere esto? Puede ser difícil obtener la mejor respuesta sin conocer su intención exacta.

  • Casi siempre es mejor hacerlo manualmente si desea visualizar una instancia de su clase de una manera específica. Esto incluirá exactamente lo que desea y no incluirá lo que no desea, y el orden será predecible.

    Si está buscando una manera de mostrar el contenido de una clase, formatee manualmente los atributos que le interesan y proporcione este como el método __str__ o __repr__ para su clase.

  • Si desea conocer qué métodos existen para que un objeto entienda cómo funciona, use help. help(a) le mostrará un resultado formateado sobre la clase del objeto en función de sus documentos.

  • dir existe para obtener programáticamente todos los atributos de un objeto. (Acceder al __dict__ hace algo que agruparía como el mismo, pero que no utilizaría yo mismo). Sin embargo, esto puede no incluir las cosas que desea y puede incluir cosas que no desea. No es confiable y las personas piensan que lo quieren mucho más a menudo que ellos.

  • En una nota algo ortogonal, hay muy poco soporte para Python 3 en este momento. Si está interesado en escribir software real, va a querer cosas de terceros como numpy, lxml, Twisted, PIL o cualquier cantidad de frameworks web que aún no sean compatibles con Python 3 y no tengan planes en un futuro demasiado pronto. Las diferencias entre 2.6 y la rama 3.x son pequeñas, pero la diferencia en el soporte de la biblioteca es enorme.

+2

Solo quiero señalar que, cinco años después (ahora), creo que todos los módulos de terceros que mencionas admiten python3. Fuente: https://python3wos.appspot.com/ – pzkpfw

90
dir(instance) 
# or 
instance.__dict__ 

A continuación, puede probar qué tipo es con type() o si es un método con callable().

+2

'llamable' no existe en py3k – SilentGhost

+3

(y probablemente no debería usarse en Python 2.) –

+0

dir funcionó mejor en clases con atributo sobrecargado get/set – ogurets

38

vars(obj) devuelve los atributos de un objeto.

+6

Solo funciona para atributos __dict__. –

6

Hay más de una manera de hacerlo:

#! /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)) 

Cuando se ejecuta, este código produce:

[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

¿Por qué esta respuesta ha sido expirada? Para fines de depuración, dir funciona bastante bien! – Dunatotatos

+0

Pretty funciona con Python 2.7.x.Exactamente lo que quería. –

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

No funciona con los nombres de atributos de clase comenzando con una letra mayúscula o un guión bajo único. – fviktor

7

A menudo se menciona que para enumerar una lista completa de los atributos que debería usar dir(). Sin embargo, tenga en cuenta que, contrariamente a la creencia popular, dir() no pone de manifiesto todos los atributos. Por ejemplo, es posible que observe que __name__ puede estar ausente de la lista dir() de una clase, aunque puede acceder a ella desde la misma clase. Desde el doc en dir() (Python 2, Python 3):

Debido dir() se suministra principalmente como una conveniencia para el uso en una modo interactivo, se trata de suministrar un interesante conjunto de nombres más de lo que intenta suministrar un conjunto definido rigurosamente o sistemáticamente de nombres, y su comportamiento detallado puede cambiar a lo largo de las versiones. Para el ejemplo , los atributos de metaclase no están en la lista de resultados cuando el argumento es una clase.

una función como la siguiente tiende a ser más completa, aunque no hay garantía de integridad desde la lista devuelta por dir() puede verse afectada por muchos factores, incluyendo la realización del procedimiento __dir__() o la personalización __getattr__() o __getattribute__() en la clase o uno de sus padres. Vea los enlaces provistos para más detalles.

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

favor ver la siguiente ejecución shell scripting Python en secuencia, se le dará la solución desde la creación de la clase a la extracción de los nombres de los campos de las instancias.

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

También podemos verificar la caligrafía de cada attributes.visit http://stackoverflow.com/questions/1398022/looping-over-all-member-variables-of-a-class-in-python?noredirect=1&lq=1 –

0

Como está escrito antes de usar obj.__dict__ puede manejar los casos más comunes, pero algunas clases no tienen el atributo __dict__ y utilizar __slots__ (sobre todo para la eficacia de la memoria).

ejemplo para una forma más resistente de hacer esto:

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 salida de este código:

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

Nota 1:
Python es un lenguaje dinámico y siempre es mejor saber la clases que intenta obtener los atributos, ya que incluso este código puede perder algunos casos.

Nota 2:
este código salidas no sólo se incluyen las variables de instancia que significan las variables de clase.por ejemplo:

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

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

salidas de código:

{'path': '/questions'} 

Este código no se imprime el atributo url clase y podría omitir los atributos de la clase buscada.
A veces podríamos pensar que un atributo es un miembro de instancia pero no se muestra ni se mostrará con este ejemplo.

11

El módulo inspect ofrece maneras fáciles de inspeccionar un objeto:

La inspeccionar módulo proporciona varias funciones útiles para ayudar a conseguir información sobre objetos vivos tales como módulos, clases, métodos funciones, los rastreos, marco objetos y objetos de código.


Usando getmembers() se puede ver todos los atributos de su clase, junto con su valor. Para excluir atributos privados o protegidos, use .startswith('_'). Para excluir métodos o funciones, use inspect.ismethod() o 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) 

Tenga en cuenta que ismethod() se utiliza en el segundo elemento de i ya que la primera es simplemente una cadena (su nombre).

Offtopic: Use CamelCase para los nombres de clase.

4

Consulte el script de Python Shell que se ha ejecutado en secuencia, aquí obtendrá los atributos de una clase en formato de cadena separados por comas.

>>> 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/> 

estoy usando Python 3.4

+0

Y si solo desea la lista, puede usar 'a .__ dict __. Keys()'. Sin embargo, si quiere saber si un objeto tiene un atributo específico, puede usar ['hasattr'] (http://stackoverflow.com/questions/610883/how-to-know-if-an-object-has-an- atributo en pitón). – berna1111

Cuestiones relacionadas