Is er een ingebouwde functie om alle huidige eigenschappen en waarden van een object af te drukken?

Dus wat ik hier zoek is zoiets als de print_r-functie van PHP.

Dit is zodat ik mijn scripts kan debuggen door te zien wat de status is van het object in kwestie.


Antwoord 1, autoriteit 100%

Je haalt echt twee verschillende dingen door elkaar.

Gebruik dir(), vars() of de inspect module om te krijgen waar je in geïnteresseerd bent (ik gebruik __builtins__ als voorbeeld; u kunt in plaats daarvan elk object gebruiken).

>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__

Druk dat woordenboek af zoals je wilt:

>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...

of

>>> 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',
...

Pretty printing is ook beschikbaar in de interactieve debugger als een commando:

(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__'}

Antwoord 2, autoriteit 97%

U wilt vars() gemengd met pprint():

from pprint import pprint
pprint(vars(your_object))

Antwoord 3, autoriteit 35%

def dump(obj):
  for attr in dir(obj):
    print("obj.%s = %r" % (attr, getattr(obj, attr)))

Er zijn veel functies van derden die dingen toevoegen zoals het afhandelen van uitzonderingen, het afdrukken van nationale/speciale tekens, terugkeren naar geneste objecten enz. volgens de voorkeuren van hun auteurs. Maar eigenlijk komen ze hier allemaal op neer.


Antwoord 4, autoriteit 10%

dir is genoemd, maar dat geeft je alleen de namen van de attributen. Als je ook hun waarden wilt, probeer dan __dict__.

class O:
   def __init__ (self):
      self.value = 3
o = O()

Hier is de uitvoer:

>>> o.__dict__
{'value': 3}

Antwoord 5, autoriteit 5%

Is er een ingebouwde functie om alle huidige eigenschappen en waarden van een object af te drukken?

Nee. Het meest gewaardeerde antwoord sluit bepaalde soorten attributen uit, en het geaccepteerde antwoord laat zien hoe je alle attributen kunt krijgen, inclusief methoden en delen van de niet-openbare api. Maar hier is geen goede complete ingebouwde functie voor.

Dus het korte gevolg is dat je je eigen kunt schrijven, maar het berekent eigenschappen en andere berekende gegevensdescriptors die deel uitmaken van de openbare API, en dat wil je misschien niet:

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

Problemen met andere antwoorden

Bekijk de toepassing van het momenteel best gestemde antwoord op een klas met veel verschillende soorten gegevensleden:

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

alleen afdrukken:

{'baz': 'baz'}

Omdat vars alleen de __dict__ van een object retourneert, en het geen kopie is, dus als je het dict dat door vars wordt geretourneerd, wijzigt, je wijzigt ook de __dict__ van het object zelf.

vars(obj)['quux'] = 'WHAT?!'
vars(obj)

retourneert:

{'baz': 'baz', 'quux': 'WHAT?!'}

— wat slecht is omdat quux een eigenschap is die we niet zouden moeten instellen en niet in de naamruimte zouden moeten staan…

Het toepassen van het advies in het momenteel geaccepteerde antwoord (en andere) is niet veel beter:

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

Zoals we kunnen zien, retourneert dir alleen alle (eigenlijk alleen de meeste) namen die aan een object zijn gekoppeld.

inspect.getmembers, genoemd in de opmerkingen, is eveneens gebrekkig – het retourneert alle namen en waarden.

Uit de les

Tijdens het lesgeven laat ik mijn leerlingen een functie maken die de semantisch openbare API van een object levert:

def api(obj):
    return [name for name in dir(obj) if name[0] != '_']

We kunnen dit uitbreiden om een ​​kopie van de semantische naamruimte van een object te leveren, maar we moeten __slots__ uitsluiten die niet zijn toegewezen, en als we we nemen het verzoek om “huidige eigendommen” serieus, we moeten berekende eigenschappen uitsluiten (omdat ze duur kunnen worden en kunnen worden geïnterpreteerd als niet “huidig”):

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

En nu berekenen of tonen we de eigenschap niet, quux:

>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}

Voorbehoud

Maar misschien weten we dat onze eigendommen niet duur zijn. Misschien willen we de logica veranderen om ze ook op te nemen. En misschien willen we in plaats daarvan andere aangepaste gegevensdescriptors uitsluiten.

Dan moeten we deze functie verder aanpassen. En dus is het logisch dat we geen ingebouwde functie kunnen hebben die op magische wijze precies weet wat we willen en daarin voorziet. Dit is functionaliteit die we zelf moeten creëren.

Conclusie

Er is geen ingebouwde functie die dit doet, en u moet doen wat semantisch het meest geschikt is voor uw situatie.


Antwoord 6, autoriteit 3%

U kunt hiervoor de functie “dir()” gebruiken.

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

Een andere handige functie is hulp.

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

Antwoord 7, autoriteit 3%

Om de huidige staat van het object af te drukken, kunt u:

>>> obj # in an interpreter

of

print repr(obj) # in a script

of

print obj

Definieer voor uw klassen __str__ of __repr__ methoden. Uit de Python-documentatie:

__repr__(self) Aangeroepen door de repr() ingebouwde functie en door string
conversies (omgekeerde aanhalingstekens) naar
bereken de “officiële” string
voorstelling van een object. als al
mogelijk, zou dit eruit moeten zien als een
geldige Python-expressie die zou kunnen zijn
gebruikt om een ​​object opnieuw te maken met de
dezelfde waarde (gegeven een geschikte
omgeving). Indien dit niet mogelijk is,
een string van de vorm “<…wat handig
description…>” moet worden geretourneerd.
De retourwaarde moet een tekenreeks zijn
object. Als een klasse repr() definieert
maar niet __str__(), dan is __repr__()
ook gebruikt wanneer een “informele” tekenreeks
weergave van voorbeelden daarvan
klasse is vereist. Dit is typisch
gebruikt voor debuggen, dus het is belangrijk
dat de vertegenwoordiging is
informatierijk en ondubbelzinnig.

__str__(self) Aangeroepen door de str() ingebouwde functie en door de print
verklaring om de “informele”
tekenreeksrepresentatie van een object.
Dit verschilt van __repr__() doordat:
het hoeft geen geldige Python te zijn
uitdrukking: een handiger of
beknopte weergave kan worden gebruikt
in plaats daarvan. De retourwaarde moet a . zijn
tekenreeksobject.


Antwoord 8, autoriteit 2%

Misschien de moeite van het bekijken waard —

Is er een Python-equivalent van Perl’s Data::Dumper?

Mijn aanbeveling is dit —

https://gist.github.com/1071857

Merk op dat perl een module heeft met de naam Data::Dumper die objectgegevens terugvertaalt naar perl-broncode (NB: het vertaalt code NIET terug naar de bron, en bijna altijd wilt u niet dat de objectmethode functioneert in de uitgang). Dit kan worden gebruikt voor persistentie, maar het algemene doel is om fouten op te sporen.

Er zijn een aantal dingen die standaard python pprint niet kan bereiken, met name het stopt gewoon met dalen wanneer het een instantie van een object ziet en geeft je de interne hex-aanwijzer van het object (errr, die aanwijzer is niet heel veel overigens van nut). Kortom, python draait helemaal om dit geweldige objectgeoriënteerde paradigma, maar de tools die je uit de doos krijgt, zijn ontworpen om met iets anders dan objecten te werken.

De perl Data::Dumper stelt je in staat om te bepalen hoe diep je wilt gaan, en detecteert ook cirkelvormige gekoppelde structuren (dat is erg belangrijk). Dit proces is fundamenteel gemakkelijker te bereiken in perl omdat objecten geen bijzondere magie hebben buiten hun zegen (een universeel goed gedefinieerd proces).


Antwoord 9, autoriteit 2%

Ik raad aan om help(your_object) te gebruiken.

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

Antwoord 10, autoriteit 2%

In de meeste gevallen zal het gebruik van __dict__ of dir() u de gewenste informatie opleveren. Als u meer details nodig heeft, bevat de standaardbibliotheek de module inspect, waarmee je een indrukwekkende hoeveelheid details kunt krijgen. Enkele van de echte stukjes informatie zijn:

  • namen van functie- en methodeparameters
  • klasse hiërarchieën
  • broncode van de implementatie van een functie/klasse-object
  • lokale variabelen uit een frame-object

Als u alleen zoekt naar “welke attribuutwaarden heeft mijn object?”, dan zijn dir() en __dict__ waarschijnlijk voldoende. Als je echt wilt graven in de huidige staat van willekeurige objecten (in gedachten houdend dat in python bijna alles een object is), dan is inspect het overwegen waard.


Antwoord 11, autoriteit 2%

Als je dit gebruikt voor debuggen, en je wilt gewoon een recursieve dump van alles, dan is het geaccepteerde antwoord onbevredigend omdat het vereist dat je klassen al goede __str__ implementaties hebben. Als dat niet het geval is, werkt dit veel beter:

import json
print(json.dumps(YOUR_OBJECT, 
                 default=lambda obj: vars(obj),
                 indent=1))

Antwoord 12

Een voorbeeld van metaprogrammering Dump object met magie:

$ kattendump.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

Zonder argumenten:

$ python dump.py
<__main__.Data instance at 0x00A052D8>

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

Het is een beetje verouderd, maar werkt nog steeds.


Antwoord 13

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

Uitvoer:

__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)

Antwoord 14

from pprint import pprint
def print_r(the_object):
    print ("CLASS: ", the_object.__class__.__name__, " (BASE CLASS: ", the_object.__class__.__bases__,")")
    pprint(vars(the_object))

Antwoord 15

Hiermee wordt alle objectinhoud recursief afgedrukt in json- of yaml-ingesprongen formaat:

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)

Antwoord 16

Ik heb het antwoord dat alleen pprint vermeldt, omhoog gestemd. Voor alle duidelijkheid: als je alle waarden in een complexe gegevensstructuur wilt zien, doe dan zoiets als:

from pprint import pprint
pprint(my_var)

Waarbij my_var uw interessante variabele is. Toen ik pprint(vars(my_var)) gebruikte, kreeg ik niets, en andere antwoorden hier hielpen niet of de methode leek onnodig lang. Trouwens, in mijn specifieke geval had de code die ik aan het inspecteren was een woordenboek met woordenboeken.

Het is de moeite waard om erop te wijzen dat je met sommige aangepaste klassen misschien een nutteloos <someobject.ExampleClass object at 0x7f739267f400> soort uitvoer krijgt. In dat geval moet u mogelijk een __str__-methode implementeren of enkele van de andere oplossingen proberen.

Ik ontdekte ook dat in een keer dat ik dit object uitvoertype kreeg, vars() me liet zien wat ik wilde. Dus een betere oplossing om beide gevallen te dekken, zou zijn om beide afzonderlijk te proberen. Maar het gebruik van vars() kan soms een uitzondering veroorzaken, bijvoorbeeld TypeError: vars() argument must have __dict__ attribute hebben.

Ik zou nog steeds graag iets eenvoudigs willen vinden dat in alle scenario’s werkt, zonder bibliotheken van derden.


Antwoord 17

Ik moest DEBUG-info in sommige logboeken afdrukken en kon pprint niet gebruiken omdat het deze zou breken. In plaats daarvan deed ik dit en kreeg vrijwel hetzelfde.

DO = DemoObject()
itemDir = DO.__dict__
for i in itemDir:
    print '{0}  :  {1}'.format(i, itemDir[i])

Antwoord 18

Om “myObject” te dumpen:

from bson import json_util
import json
print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))

Ik heb vars() en dir() geprobeerd; beide faalden voor wat ik zocht. vars() werkte niet omdat het object geen __dict__ had (uitzonderingen.TypeError: het argument vars() moet het kenmerk __dict__ hebben). dir() was niet wat ik zocht: het is gewoon een lijst met veldnamen, geeft niet de waarden of de objectstructuur.

Ik denk dat json.dumps() voor de meeste objecten zou werken zonder de default=json_util.default, maar ik had een datetime-veld in het object, dus de standaard json-serializer faalde. Zie Hoe “datetime.datetime not JSON serializable” te overwinnen in python?


Antwoord 19

Waarom niet iets simpels:

for key,value in obj.__dict__.iteritems():
    print key,value

Antwoord 20

pprint bevat een “mooie printer” voor het produceren van esthetisch aantrekkelijke afbeeldingen van uw datastructuren. De formatter produceert representaties van datastructuren die correct kunnen worden geparseerd door de interpreter en die ook gemakkelijk voor een mens te lezen zijn. De uitvoer wordt indien mogelijk op een enkele regel gehouden en ingesprongen wanneer deze over meerdere regels wordt verdeeld.


Antwoord 21

Voor iedereen die worstelt met

  • vars() geeft niet alle attributen terug.
  • dir() geeft de waarden van de attributen niet terug.

De volgende code drukt alle attributen van obj af met hun waarden:

for attr in dir(obj):
        try:
            print("obj.{} = {}".format(attr, getattr(obj, attr)))
        except AttributeError:
            print("obj.{} = ?".format(attr))

Antwoord 22

Probeer gewoon beeprint.

Het helpt u niet alleen bij het afdrukken van objectvariabelen, maar ook bij prachtige uitvoer, zoals deze:

class(NormalClassNewStyle):
  dicts: {
  },
  lists: [],
  static_props: 1,
  tupl: (1, 2)

Antwoord 23

U kunt de Flask Debug Toolbar proberen.
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)

Antwoord 24

Dit werkt ongeacht hoe uw variabelen binnen een klasse zijn gedefinieerd, binnen __init__ of daarbuiten.

your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}

Antwoord 25

Ik werk graag met ingebouwde typen python-objecten sleutels of waarden .

Voor attributen, ongeacht of het methoden of variabelen zijn:

o.keys()

Voor waarden van die attributen:

o.values()

LEAVE A REPLY

Please enter your comment!
Please enter your name here

6 − 6 =

Other episodes