Respuestas:
Realmente estás mezclando dos cosas diferentes.
Uso dir()
, vars()
o el inspect
módulo para conseguir lo que le interesa (utilizo __builtins__
como ejemplo, se puede utilizar cualquier objeto en su lugar).
>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__
Imprime ese diccionario como quieras:
>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...
o
>>> from pprint import pprint
>>> pprint(l)
['ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'DeprecationWarning',
...
>>> pprint(d, indent=2)
{ 'ArithmeticError': <type 'exceptions.ArithmeticError'>,
'AssertionError': <type 'exceptions.AssertionError'>,
'AttributeError': <type 'exceptions.AttributeError'>,
...
'_': [ 'ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'DeprecationWarning',
...
La impresión bonita también está disponible en el depurador interactivo como un comando:
(Pdb) pp vars()
{'__builtins__': {'ArithmeticError': <type 'exceptions.ArithmeticError'>,
'AssertionError': <type 'exceptions.AssertionError'>,
'AttributeError': <type 'exceptions.AttributeError'>,
'BaseException': <type 'exceptions.BaseException'>,
'BufferError': <type 'exceptions.BufferError'>,
...
'zip': <built-in function zip>},
'__file__': 'pass.py',
'__name__': '__main__'}
print re.compile(r'slots').search('No slots here either.').__slots__
inspect
módulo en tu respuesta? Creo que es lo más parecido a print_r o var_dump.
dir()
, entonces? dir()
solo devuelve una lista de nombres, y no todos existen en vars()
o en el __dict__
atributo.
Quieres vars()
mezclar con pprint()
:
from pprint import pprint
pprint(vars(your_object))
vars()
simplemente devuelve el __dict__
de su argumento y ese también es el respaldo de dir()
en caso de que no haya ningún __dir__
método. así que dir()
en primer lugar, como dije.
dir()
te ofrece todas las cosas integradas que probablemente no te interesen __str__
y __new__
. var()
no lo hace
__dict__
atributo.
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
Existen muchas funciones de terceros que agregan cosas como manejo de excepciones, impresión de caracteres nacionales / especiales, recursión en objetos anidados, etc. de acuerdo con las preferencias de sus autores. Pero todos básicamente se reducen a esto.
getmembers()
función en el inspect
módulo estándar , pero pensé que esto sería más útil ya que ilustra cómo hacer la introspección en general.
__dict__
(como __doc__
y __module__
). Además, __dict__
no funciona en absoluto para los objetos declarados con __slots__
. En general, __dict__
muestra las propiedades de nivel de usuario que realmente se almacenan internamente en un diccionario. dir () muestra más.
__dict__
atributo / miembro. Sé que es una locura, pero cierto. Los empotrados como int
y str
o re.MatchObject
s son ejemplos comunes. Intenta 'hello'.__dict__
, luego intentadir('hello')
se ha mencionado dir , pero eso solo le dará los nombres de los atributos. Si también quieres sus valores, prueba __dict__.
class O:
def __init__ (self):
self.value = 3
o = O()
Aquí está la salida:
>>> o.__dict__
{'value': 3}
set
no tiene __dict__
, por lo que para ellos fallaráAttributeError: 'set' object has no attribute '__dict__'
Puede usar la función "dir ()" para hacer esto.
>>> import sys
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdo
t__', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder
, 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'exc_clear', 'exc_info'
'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefault
ncoding', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcount', 'getwindowsversion', 'he
version', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_
ache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit
, 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoption
', 'winver']
>>>
Otra característica útil es la ayuda.
>>> help(sys)
Help on built-in module sys:
NAME
sys
FILE
(built-in)
MODULE DOCS
http://www.python.org/doc/current/lib/module-sys.html
DESCRIPTION
This module provides access to some objects used or maintained by the
interpreter and to functions that interact strongly with the interpreter.
Dynamic objects:
argv -- command line arguments; argv[0] is the script pathname if known
Para imprimir el estado actual del objeto, puede:
>>> obj # in an interpreter
o
print repr(obj) # in a script
o
print obj
Para sus clases definir __str__
o __repr__
métodos. De la documentación de Python :
__repr__(self)
Llamado por larepr()
función incorporada y por las conversiones de cadena (comillas inversas) para calcular la representación de cadena "oficial" de un objeto. Si es posible, esto debería verse como una expresión Python válida que podría usarse para recrear un objeto con el mismo valor (dado un entorno apropiado). Si esto no es posible, se debe devolver una cadena de la forma "<... alguna descripción útil ...>". El valor de retorno debe ser un objeto de cadena. Si una clase define repr () pero no__str__()
, entonces__repr__()
también se usa cuando se requiere una representación de cadena "informal" de instancias de esa clase. Esto generalmente se usa para la depuración, por lo que es importante que la representación sea rica en información y sin ambigüedades.
__str__(self)
Llamado por lastr()
función incorporada y por la instrucción print para calcular la representación de cadena "informal" de un objeto. Esto difiere de__repr__()
que no tiene que ser una expresión Python válida: en su lugar, se puede usar una representación más conveniente o concisa. El valor de retorno debe ser un objeto de cadena.
print "DEBUG: object value: " + repr(obj)
Podría valer la pena echarle un vistazo --
¿Hay un Python equivalente a Perl's Data :: Dumper?
Mi recomendación es esta:
https://gist.github.com/1071857
Tenga en cuenta que perl tiene un módulo llamado Data :: Dumper que traduce los datos del objeto nuevamente al código fuente de perl (NB: NO traduce el código nuevamente a la fuente, y casi siempre no desea que las funciones del método del objeto en la salida). Esto puede usarse para la persistencia, pero el propósito común es la depuración.
Hay una serie de cosas que el pprint estándar de Python no logra, en particular, simplemente deja de descender cuando ve una instancia de un objeto y le da el puntero hexadecimal interno del objeto (errr, ese puntero no es muy utilizado por la manera). En pocas palabras, python tiene que ver con este gran paradigma orientado a objetos, pero las herramientas que obtiene de la caja están diseñadas para trabajar con algo que no sean objetos.
El perl Data :: Dumper le permite controlar qué tan profundo quiere llegar, y también detecta estructuras enlazadas circulares (eso es realmente importante). Este proceso es fundamentalmente más fácil de lograr en perl porque los objetos no tienen magia particular más allá de su bendición (un proceso universalmente bien definido).
Recomiendo usar help(your_object)
.
help(dir)
If called without an argument, return the names in the current scope. Else, return an alphabetized list of names comprising (some of) the attributes of the given object, and of attributes reachable from it. If the object supplies a method named __dir__, it will be used; otherwise the default dir() logic is used and returns: for a module object: the module's attributes. for a class object: its attributes, and recursively the attributes of its bases. for any other object: its attributes, its class's attributes, and recursively the attributes of its class's base classes.
help(vars)
Without arguments, equivalent to locals(). With an argument, equivalent to object.__dict__.
En la mayoría de los casos, usar __dict__
o dir()
le proporcionará la información que desea. Si necesita más detalles, la biblioteca estándar incluye el módulo de inspección , que le permite obtener una cantidad impresionante de detalles. Algunos de los detalles más reales de información incluyen:
Si solo está buscando "¿qué valores de atributo tiene mi objeto?", Entonces dir()
y __dict__
probablemente sean suficientes. Si realmente está buscando profundizar en el estado actual de los objetos arbitrarios (teniendo en cuenta que en Python casi todo es un objeto), entonces inspect
es digno de consideración.
¿Existe una función incorporada para imprimir todas las propiedades y valores actuales de un objeto?
No. La respuesta más votada excluye algunos tipos de atributos, y la respuesta aceptada muestra cómo obtener todos los atributos, incluidos los métodos y partes de la API no pública. Pero no hay una buena completa incorporado la función de este.
Entonces, el corto corolario es que puede escribir el suyo propio, pero calculará las propiedades y otros descriptores de datos calculados que son parte de la API pública, y es posible que no desee eso:
from pprint import pprint
from inspect import getmembers
from types import FunctionType
def attributes(obj):
disallowed_names = {
name for name, value in getmembers(type(obj))
if isinstance(value, FunctionType)}
return {
name: getattr(obj, name) for name in dir(obj)
if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)}
def print_attributes(obj):
pprint(attributes(obj))
Observe la aplicación de la respuesta más votada actualmente en una clase con muchos tipos diferentes de miembros de datos:
from pprint import pprint
class Obj:
__slots__ = 'foo', 'bar', '__dict__'
def __init__(self, baz):
self.foo = ''
self.bar = 0
self.baz = baz
@property
def quux(self):
return self.foo * self.bar
obj = Obj('baz')
pprint(vars(obj))
solo impresiones:
{'baz': 'baz'}
Porque vars
solo devuelve el __dict__
de un objeto, y no es una copia, por lo que si modifica el dict devuelto por vars, también está modificando el __dict__
del objeto en sí.
vars(obj)['quux'] = 'WHAT?!'
vars(obj)
devoluciones:
{'baz': 'baz', 'quux': 'WHAT?!'}
- lo cual es malo porque quux es una propiedad que no deberíamos configurar y no deberíamos estar en el espacio de nombres ...
Aplicar el consejo en la respuesta actualmente aceptada (y otras) no es mucho mejor:
>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar', 'baz', 'foo', 'quux']
Como podemos ver, dir
solo devuelve todos (en realidad solo la mayoría) de los nombres asociados con un objeto.
inspect.getmembers
, mencionado en los comentarios, tiene fallas similares: devuelve todos los nombres y valores.
Cuando enseño, mis alumnos crean una función que proporciona la API semánticamente pública de un objeto:
def api(obj):
return [name for name in dir(obj) if name[0] != '_']
Podemos extender esto para proporcionar una copia del espacio de nombres semántico de un objeto, pero debemos excluir los __slots__
que no están asignados, y si nos tomamos en serio la solicitud de "propiedades actuales", debemos excluir las propiedades calculadas (como podrían volverse caros y podrían interpretarse como no "actuales"):
from types import FunctionType
from inspect import getmembers
def attrs(obj):
disallowed_properties = {
name for name, value in getmembers(type(obj))
if isinstance(value, (property, FunctionType))}
return {
name: getattr(obj, name) for name in api(obj)
if name not in disallowed_properties and hasattr(obj, name)}
Y ahora no calculamos ni mostramos la propiedad, quux:
>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}
Pero quizás sabemos que nuestras propiedades no son caras. Es posible que queramos alterar la lógica para incluirlos también. Y tal vez queremos excluir otros descriptores de datos personalizados .
Entonces necesitamos personalizar aún más esta función. Y entonces tiene sentido que no podamos tener una función incorporada que mágicamente sepa exactamente lo que queremos y lo proporcione. Esta es la funcionalidad que necesitamos para crearnos.
No hay una función integrada que haga esto, y debe hacer lo que sea más semánticamente apropiado para su situación.
FunctionType
. Pero muy útil, ¡gracias!
Un ejemplo de metaprogramación Volcar objeto con magia :
$ cat dump.py
#!/usr/bin/python
import sys
if len(sys.argv) > 2:
module, metaklass = sys.argv[1:3]
m = __import__(module, globals(), locals(), [metaklass])
__metaclass__ = getattr(m, metaklass)
class Data:
def __init__(self):
self.num = 38
self.lst = ['a','b','c']
self.str = 'spam'
dumps = lambda self: repr(self)
__str__ = lambda self: self.dumps()
data = Data()
print data
Sin argumentos:
$ python dump.py
<__main__.Data instance at 0x00A052D8>
Con Gnosis Utils :
$ python dump.py gnosis.magic MetaXMLPickler
<?xml version="1.0"?>
<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
<PyObject module="__main__" class="Data" id="11038416">
<attr name="lst" type="list" id="11196136" >
<item type="string" value="a" />
<item type="string" value="b" />
<item type="string" value="c" />
</attr>
<attr name="num" type="numeric" value="38" />
<attr name="str" type="string" value="spam" />
</PyObject>
Está un poco anticuado pero sigue funcionando.
Si está utilizando esto para la depuración, y solo desea un volcado recursivo de todo, la respuesta aceptada es insatisfactoria porque requiere que sus clases ya tengan buenas __str__
implementaciones. Si ese no es el caso, esto funciona mucho mejor:
import json
print(json.dumps(YOUR_OBJECT,
default=lambda obj: vars(obj),
indent=1))
TypeError: vars() argument must have __dict__ attribute
Prueba ppretty
from ppretty import ppretty
class A(object):
s = 5
def __init__(self):
self._p = 8
@property
def foo(self):
return range(10)
print ppretty(A(), show_protected=True, show_static=True, show_properties=True)
Salida:
__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)
Esto imprime todo el contenido del objeto de forma recursiva en formato sangrado json o yaml:
import jsonpickle # pip install jsonpickle
import json
import yaml # pip install pyyaml
serialized = jsonpickle.encode(obj, max_depth=2) # max_depth is optional
print json.dumps(json.loads(serialized), indent=4)
print yaml.dump(yaml.load(serialized), indent=4)
He votado a favor la respuesta que menciona solo pprint. Para ser claros, si desea ver todos los valores en una estructura de datos compleja, haga algo como:
from pprint import pprint
pprint(my_var)
Donde my_var es tu variable de interés. Cuando lo usé pprint(vars(my_var))
no obtuve nada, y otras respuestas aquí no ayudaron o el método parecía innecesariamente largo. Por cierto, en mi caso particular, el código que estaba inspeccionando tenía un diccionario de diccionarios.
Vale la pena señalar que con algunas clases personalizadas puede terminar con una inútil <someobject.ExampleClass object at 0x7f739267f400>
tipo de salida . En ese caso, es posible que deba implementar un __str__
método o probar algunas de las otras soluciones. Todavía me gustaría encontrar algo simple que funcione en todos los escenarios, sin bibliotecas de terceros.
Para volcar "myObject":
from bson import json_util
import json
print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))
Probé vars () y dir (); ambos fallaron por lo que estaba buscando. vars () no funcionó porque el objeto no tenía __dict__ (excepciones.TypeError: el argumento vars () debe tener el atributo __dict__). dir () no era lo que estaba buscando: es solo una lista de nombres de campo, no da los valores o la estructura del objeto.
Creo que json.dumps () funcionaría para la mayoría de los objetos sin default = json_util.default, pero tenía un campo de fecha y hora en el objeto, por lo que el serializador json estándar falló. Consulte ¿Cómo superar "datetime.datetime no JSON serializable" en python?
¿Por qué no algo simple?
for key,value in obj.__dict__.iteritems():
print key,value
for key,value in obj.__dict__.iteritems(): print key,value
?
pprint contiene una "bonita impresora" para producir representaciones estéticamente agradables de sus estructuras de datos. El formateador produce representaciones de estructuras de datos que el intérprete puede analizar correctamente, y también son fáciles de leer para un humano. La salida se mantiene en una sola línea, si es posible, y se sangra cuando se divide en varias líneas.
Solo prueba beeprint .
Le ayudará no solo a imprimir variables de objeto, sino también a una salida hermosa, como esta:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)
Para todos los que luchan con
vars()
No devuelve todos los atributos. dir()
no devuelve los valores de los atributos.El siguiente código imprime todos los atributos de obj
con sus valores:
for attr in dir(obj):
try:
print("obj.{} = {}".format(attr, getattr(obj, attr)))
except AttributeError:
print("obj.{} = ?".format(attr))
Puede probar la barra de herramientas de depuración de frascos.
https://pypi.python.org/pypi/Flask-DebugToolbar
from flask import Flask
from flask_debugtoolbar import DebugToolbarExtension
app = Flask(__name__)
# the toolbar is only enabled in debug mode:
app.debug = True
# set a 'SECRET_KEY' to enable the Flask session cookies
app.config['SECRET_KEY'] = '<replace with a secret key>'
toolbar = DebugToolbarExtension(app)
Me gusta trabajar con claves o valores de tipos integrados de objetos de Python .
Para los atributos independientemente de que sean métodos o variables:
o.keys()
Para valores de esos atributos:
o.values()
Esto funciona sin importar cómo se definan sus variables dentro de una clase, dentro de __init__ o afuera.
your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
__dict__
miembro (unre.MatchObject
por ejemplo), pero incorporadodir()
funciona para todos los objetos.