Odpowiedzi:
Naprawdę łączysz dwie różne rzeczy.
Stosowanie dir()
, vars()
lub inspect
moduł, aby uzyskać to, co jesteś zainteresowany (używam __builtins__
jako przykład, można użyć dowolnego obiektu zamiast).
>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__
Wydrukuj ten słownik, jakkolwiek lubisz:
>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...
lub
>>> 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',
...
Ładne drukowanie jest również dostępne w interaktywnym debuggerze jako polecenie:
(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
w swojej odpowiedzi nie mówisz więcej o module? Myślę, że to najbliższa rzecz do print_r lub var_dump.
dir()
? dir()
zwraca tylko listę nazw i nie wszystkie istnieją w atrybucie vars()
lub w nim __dict__
.
Chcesz vars()
mieszać z pprint()
:
from pprint import pprint
pprint(vars(your_object))
vars()
po prostu zwraca __dict__
argument swojego argumentu i jest to również awaria dir()
w przypadku braku __dir__
metody. więc używaj dir()
przede wszystkim, jak powiedziałem.
dir()
zawiera wszystkie wbudowane rzeczy, o których prawdopodobnie nie dbacie, jak __str__
i __new__
. var()
nie.
__dict__
atrybutu.
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
Istnieje wiele funkcji innych firm, które dodają takie funkcje, jak obsługa wyjątków, drukowanie znaków narodowych / specjalnych, rekurencja w zagnieżdżone obiekty itp. Zgodnie z preferencjami ich autorów. Ale wszystkie one w zasadzie sprowadzają się do tego.
getmembers()
funkcji w standardowym inspect
module, ale pomyślałem, że byłoby to bardziej przydatne, ponieważ ilustruje ogólnie, jak robić introspekcję.
__dict__
(takich jak __doc__
i __module__
). Ponadto w __dict__
ogóle nie działa dla obiektów zadeklarowanych za pomocą __slots__
. Zasadniczo __dict__
pokazuje właściwości na poziomie użytkownika, które są faktycznie przechowywane wewnętrznie w słowniku. dir () pokazuje więcej.
__dict__
atrybutu / członka. Wiem, że to szalone, ale prawdziwe. Wbudowane, takie jak int
i str
lub re.MatchObject
s, są typowymi przykładami. Spróbuj 'hello'.__dict__
, a następnie spróbujdir('hello')
dir został wspomniany, ale to da ci tylko nazwy atrybutów. Jeśli chcesz również ich wartości, spróbuj __dict__.
class O:
def __init__ (self):
self.value = 3
o = O()
Oto wynik:
>>> o.__dict__
{'value': 3}
set
nie mają __dict__
, więc dla nich się nie powiedzieAttributeError: 'set' object has no attribute '__dict__'
Aby to zrobić, możesz użyć funkcji „dir ()”.
>>> 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']
>>>
Kolejną przydatną funkcją jest pomoc.
>>> 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
Aby wydrukować bieżący stan obiektu, możesz:
>>> obj # in an interpreter
lub
print repr(obj) # in a script
lub
print obj
Dla twoich klas zdefiniuj __str__
lub zastosuj __repr__
metody. Z dokumentacji Python :
__repr__(self)
Wywoływany przezrepr()
wbudowaną funkcję i konwersję ciągów (odwrotne cudzysłowy) w celu obliczenia „oficjalnej” reprezentacji ciągu obiektu. Jeśli to w ogóle możliwe, powinno to wyglądać jak prawidłowe wyrażenie w języku Python, którego można użyć do odtworzenia obiektu o tej samej wartości (przy odpowiednim środowisku). Jeśli nie jest to możliwe, należy zwrócić ciąg znaków „<... użyteczny opis ...>”. Zwracana wartość musi być obiektem łańcuchowym. Jeśli klasa definiuje repr (), ale nie jest używana__str__()
, to__repr__()
jest również używana, gdy wymagana jest „nieformalna” reprezentacja ciągu instancji tej klasy. Jest to zwykle używane do debugowania, dlatego ważne jest, aby reprezentacja była bogata w informacje i jednoznaczna.
__str__(self)
Wywoływany przezstr()
wbudowaną funkcję i instrukcję print w celu obliczenia „nieformalnej” reprezentacji ciągu obiektu. Różni się__repr__()
to tym, że nie musi to być prawidłowe wyrażenie w języku Python: zamiast tego można użyć wygodniejszej lub zwięzłej reprezentacji. Zwracana wartość musi być obiektem łańcuchowym.
print "DEBUG: object value: " + repr(obj)
Może warto to sprawdzić -
Czy istnieje Python równoważny Perlowi Data :: Dumper?
Moje zalecenie jest następujące -
https://gist.github.com/1071857
Zauważ, że perl ma moduł o nazwie Data :: Dumper, który tłumaczy dane obiektowe z powrotem na kod źródłowy perla (UWAGA: NIE tłumaczy kodu z powrotem na źródło i prawie zawsze nie chcesz, aby funkcja metody obiektowej na wyjściu). Można tego użyć do trwałości, ale wspólnym celem jest debugowanie.
Istnieje wiele rzeczy, których nie osiąga standardowy wydruk w Pythonie, w szczególności przestaje opadać, gdy widzi instancję obiektu i daje wewnętrzny wskaźnik heksadecymalny obiektu (errr, ten wskaźnik nie jest zbyt często używany przez droga). Krótko mówiąc, w Pythonie chodzi o ten wspaniały paradygmat zorientowany obiektowo, ale narzędzia, które dostajesz po wyjęciu z pudełka, są zaprojektowane do pracy z czymś innym niż obiekty.
Perl Data :: Dumper pozwala kontrolować głębokość, którą chcesz zejść, a także wykrywa okrągłe struktury połączone (to naprawdę ważne). Proces ten jest zasadniczo łatwiejszy do zrealizowania w Perlu, ponieważ obiekty nie mają żadnej szczególnej magii poza ich błogosławieństwem (proces powszechnie zdefiniowany).
Polecam używać 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__.
W większości przypadków przy użyciu __dict__
lub dir()
otrzymasz informacje, których potrzebujesz. Jeśli potrzebujesz więcej szczegółów, standardowa biblioteka zawiera moduł inspekcji , który pozwala uzyskać imponującą ilość szczegółów. Niektóre z prawdziwych sugestii informacji obejmują:
Jeśli szukasz po prostu „co robi mój wartości atrybutu obiektu mają?”, A potem dir()
i __dict__
są prawdopodobnie wystarczające. Jeśli naprawdę chcesz zagłębić się w bieżący stan dowolnych obiektów (pamiętając, że w pythonie prawie wszystko jest przedmiotem), inspect
to warto go rozważyć.
Czy jest wbudowana funkcja do drukowania wszystkich bieżących właściwości i wartości obiektu?
Nie. Najpopularniejsza odpowiedź wyklucza niektóre rodzaje atrybutów, a zaakceptowana odpowiedź pokazuje, jak uzyskać wszystkie atrybuty, w tym metody i części niepublicznego interfejsu API. Ale nie ma do tego dobrej kompletnej wbudowanej funkcji.
Zatem następstwem jest to, że możesz napisać własny, ale będzie on obliczał właściwości i inne obliczone deskryptory danych, które są częścią publicznego interfejsu API, i możesz tego nie chcieć:
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))
Obserwuj zastosowanie obecnie najlepiej głosowanej odpowiedzi w klasie z wieloma różnymi rodzajami członków danych:
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))
drukuje tylko:
{'baz': 'baz'}
Ponieważ zwraca vars
tylko__dict__
obiekt, a nie kopię, więc jeśli zmodyfikujesz dykt zwrócony przez vars, zmodyfikujesz również __dict__
sam obiekt.
vars(obj)['quux'] = 'WHAT?!'
vars(obj)
zwroty:
{'baz': 'baz', 'quux': 'WHAT?!'}
- co jest złe, ponieważ quux jest właściwością, której nie powinniśmy ustawiać i nie powinniśmy znajdować się w przestrzeni nazw ...
Zastosowanie porady w obecnie akceptowanej odpowiedzi (i innych) nie jest dużo lepsze:
>>> 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']
Jak widzimy, dir
zwraca tylko wszystkie (właściwie tylko większość) nazw związanych z obiektem.
inspect.getmembers
, wspomniane w komentarzach, jest podobnie wadliwe - zwraca wszystkie nazwy i wartości.
Podczas nauczania mam uczniów, którzy tworzą funkcję, która zapewnia semantycznie publiczny interfejs API obiektu:
def api(obj):
return [name for name in dir(obj) if name[0] != '_']
Możemy to rozszerzyć, aby uzyskać kopię semantycznej przestrzeni nazw obiektu, ale musimy wykluczyć __slots__
, które nie są przypisane, a jeśli poważnie traktujemy żądanie „bieżących właściwości”, musimy wykluczyć właściwości obliczone (ponieważ mogą stać się drogie i mogą być interpretowane jako nie „aktualne”):
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)}
A teraz nie obliczamy ani nie pokazujemy właściwości, quux:
>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}
Ale może wiemy, że nasze nieruchomości nie są drogie. Możemy chcieć zmienić logikę, aby również je uwzględnić. Być może zamiast tego chcemy wykluczyć inne niestandardowe deskryptory danych.
Następnie musimy dodatkowo dostosować tę funkcję. Ma to zatem sens, że nie możemy mieć wbudowanej funkcji, która magicznie dokładnie wie, czego chcemy i zapewnia to. To funkcjonalność, którą sami musimy stworzyć.
Nie ma wbudowanej funkcji, która to robi, i powinieneś robić to, co jest najbardziej semantycznie odpowiednie dla twojej sytuacji.
FunctionType
. Ale bardzo pomocne - dzięki!
Przykład metaprogramowania Zrzuć obiekt za pomocą magii :
$ 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
Bez argumentów:
$ python dump.py
<__main__.Data instance at 0x00A052D8>
Z 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>
Jest trochę przestarzały, ale nadal działa.
Jeśli używasz tego do debugowania i chcesz po prostu rekurencyjnego zrzutu wszystkiego, zaakceptowana odpowiedź jest niezadowalająca, ponieważ wymaga, aby Twoje klasy miały __str__
już dobre implementacje. Jeśli tak nie jest, działa to znacznie lepiej:
import json
print(json.dumps(YOUR_OBJECT,
default=lambda obj: vars(obj),
indent=1))
TypeError: vars() argument must have __dict__ attribute
Spróbuj 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)
Wynik:
__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)
Spowoduje to wydrukowanie całej zawartości obiektu rekurencyjnie w formacie wcięcia w formacie json lub 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)
Głosowałem za odpowiedzią, która wymienia tylko pprint. Dla jasności, jeśli chcesz zobaczyć wszystkie wartości w złożonej strukturze danych, zrób coś takiego:
from pprint import pprint
pprint(my_var)
Gdzie my_var jest Twoją zmienną zainteresowania. Kiedy użyłem pprint(vars(my_var))
, nic nie dostałem, a inne odpowiedzi tutaj nie pomogły lub metoda wyglądała niepotrzebnie długo. Nawiasem mówiąc, w moim szczególnym przypadku kod, który sprawdzałem, miał słownik słowników.
Warto zauważyć, że w przypadku niektórych klas niestandardowych może dojść do niepomocnego <someobject.ExampleClass object at 0x7f739267f400>
wyniku. W takim przypadku może być konieczne zaimplementowanie __str__
metody lub wypróbowanie niektórych innych rozwiązań. Wciąż chciałbym znaleźć coś prostego, co zadziała we wszystkich scenariuszach, bez bibliotek stron trzecich.
Musiałem wydrukować informacje o DEBUGIE w niektórych logach i nie mogłem użyć pprint, ponieważ może to spowodować uszkodzenie. Zamiast tego zrobiłem to i dostałem praktycznie to samo.
DO = DemoObject()
itemDir = DO.__dict__
for i in itemDir:
print '{0} : {1}'.format(i, itemDir[i])
Aby zrzucić „myObject”:
from bson import json_util
import json
print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))
Próbowałem vars () i dir (); oba zawiodły w tym, czego szukałem. Funkcja vars () nie działała, ponieważ obiekt nie miał __dict__ (wyjątki.TypeError: argument vars () musi mieć atrybut __dict__). dir () nie był tym, czego szukałem: to tylko lista nazw pól, nie podaje wartości ani struktury obiektu.
Myślę, że json.dumps () działałby dla większości obiektów bez wartości domyślnej = json_util.default, ale miałem w obiekcie pole daty i godziny, więc standardowy serializator json nie powiódł się. Zobacz Jak przezwyciężyć „datetime.datetime not JSON serializable” w pythonie?
Dlaczego nie coś prostego:
for key,value in obj.__dict__.iteritems():
print key,value
for key,value in obj.__dict__.iteritems(): print key,value
?
pprint zawiera „ładną drukarkę” do tworzenia estetycznych reprezentacji twoich struktur danych. Formater tworzy reprezentacje struktur danych, które mogą być poprawnie przeanalizowane przez interpretera, a także łatwe do odczytania przez człowieka. Dane wyjściowe są przechowywane w jednym wierszu, jeśli to możliwe, i wcięte, gdy są dzielone na wiele wierszy.
Po prostu wypróbuj beeprint .
Pomoże ci to nie tylko w drukowaniu zmiennych obiektowych, ale także w pięknych wynikach, takich jak:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)
Dla wszystkich, którzy walczą
vars()
nie zwraca wszystkich atrybutów. dir()
nie zwraca wartości atrybutów.Poniższy kod wyświetla wszystkie atrybuty obj
wraz z ich wartościami:
for attr in dir(obj):
try:
print("obj.{} = {}".format(attr, getattr(obj, attr)))
except AttributeError:
print("obj.{} = ?".format(attr))
Możesz wypróbować pasek narzędzi debugowania Flask.
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)
Lubię pracować z kluczami lub wartościami wbudowanych obiektów Pythona .
W przypadku atrybutów, niezależnie od tego, czy są to metody lub zmienne:
o.keys()
Dla wartości tych atrybutów:
o.values()
Działa to bez względu na to, jak zdefiniowane są zmienne w klasie, wewnątrz __init__ lub na zewnątrz.
your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
__dict__
członkowski (re.MatchObject
na przykład), ale wbudowanedir()
działa dla wszystkich obiektów.