Jawaban:
Anda benar-benar mencampurkan dua hal yang berbeda.
Gunakan dir()
, vars()
atau inspect
modul untuk mendapatkan apa yang Anda minati (saya gunakan __builtins__
sebagai contoh; Anda bisa menggunakan objek apa saja).
>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__
Cetak kamus itu sesuka Anda:
>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...
atau
>>> 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',
...
Pencetakan cantik juga tersedia di debugger interaktif sebagai perintah:
(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
modul dalam jawaban Anda? Saya pikir itu adalah hal yang paling dekat dengan print_r atau var_dump.
dir()
, lalu? dir()
hanya mengembalikan daftar nama, dan tidak semua yang ada di vars()
atau dalam __dict__
atribut.
Anda ingin vars()
dicampur dengan pprint()
:
from pprint import pprint
pprint(vars(your_object))
vars()
hanya mengembalikan __dict__
argumennya dan itu juga mundur dir()
jika tidak ada __dir__
metode. jadi gunakan dir()
di tempat pertama, seperti yang saya katakan.
dir()
memberi Anda semua hal bawaan yang mungkin tidak Anda sukai __str__
dan __new__
. var()
tidak.
__dict__
atribut.
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
Ada banyak fungsi pihak ke-3 di luar sana yang menambahkan hal-hal seperti penanganan pengecualian, pencetakan karakter nasional / khusus, berulang ke objek bersarang dll sesuai dengan preferensi penulisnya. Tapi mereka semua pada dasarnya bermuara pada hal ini.
getmembers()
fungsi dalam inspect
modul standar , tetapi saya pikir ini akan lebih berguna karena menggambarkan bagaimana melakukan introspeksi secara umum.
__dict__
(seperti __doc__
dan __module__
). Selain itu, __dict__
tidak berfungsi sama sekali untuk objek yang dideklarasikan __slots__
. Secara umum, __dict__
memperlihatkan properti tingkat pengguna yang sebenarnya disimpan dalam kamus secara internal. dir () menunjukkan lebih banyak.
__dict__
atribut / anggota. Saya tahu ini gila, tetapi benar. Built-in like int
dan str
atau re.MatchObject
s adalah contoh umum. Coba 'hello'.__dict__
, lalu cobadir('hello')
dir telah disebutkan, tetapi itu hanya akan memberi Anda nama atribut. Jika Anda ingin nilainya juga coba __dict__.
class O:
def __init__ (self):
self.value = 3
o = O()
Berikut hasilnya:
>>> o.__dict__
{'value': 3}
set
tidak memiliki __dict__
, jadi bagi mereka itu akan gagal denganAttributeError: 'set' object has no attribute '__dict__'
Anda dapat menggunakan fungsi "dir ()" untuk melakukan ini.
>>> 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']
>>>
Fitur lain yang bermanfaat adalah bantuan.
>>> 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
Untuk mencetak keadaan objek saat ini, Anda mungkin:
>>> obj # in an interpreter
atau
print repr(obj) # in a script
atau
print obj
Untuk kelas Anda tentukan __str__
atau __repr__
metode. Dari dokumentasi Python :
__repr__(self)
Dipanggil olehrepr()
fungsi bawaan dan oleh konversi string (tanda kutip terbalik) untuk menghitung representasi string "resmi" dari suatu objek. Jika memungkinkan, ini akan terlihat seperti ekspresi Python yang valid yang dapat digunakan untuk membuat ulang objek dengan nilai yang sama (diberikan lingkungan yang sesuai). Jika ini tidak memungkinkan, string bentuk "<... beberapa deskripsi bermanfaat ...>" harus dikembalikan. Nilai kembali harus berupa objek string. Jika kelas mendefinisikan repr () tetapi tidak__str__()
, maka__repr__()
juga digunakan ketika representasi string "informal" dari instance kelas itu diperlukan. Ini biasanya digunakan untuk debugging, jadi penting agar representasi kaya informasi dan tidak ambigu.
__str__(self)
Dipanggil olehstr()
fungsi bawaan dan oleh pernyataan cetak untuk menghitung representasi string "informal" dari suatu objek. Ini berbeda dari__repr__()
yang tidak harus ekspresi Python yang valid: representasi yang lebih nyaman atau ringkas dapat digunakan sebagai gantinya. Nilai kembali harus berupa objek string.
print "DEBUG: object value: " + repr(obj)
Mungkin patut dicoba -
Apakah ada Python yang setara dengan Data Perl :: Dumper?
Rekomendasi saya adalah ini -
https://gist.github.com/1071857
Perhatikan bahwa perl memiliki modul bernama Data :: Dumper yang menerjemahkan data objek kembali ke kode sumber perl (NB: TIDAK menerjemahkan kode kembali ke sumber, dan hampir selalu Anda tidak ingin fungsi metode objek di output). Ini dapat digunakan untuk kegigihan, tetapi tujuan umumnya adalah untuk debugging.
Ada beberapa hal yang tidak dapat dicapai oleh jejak python standar, khususnya ia hanya berhenti turun ketika ia melihat instance objek dan memberi Anda pointer hex internal objek (errr, pointer itu tidak banyak digunakan oleh jalan). Jadi singkatnya, python adalah semua tentang paradigma berorientasi objek yang hebat ini, tetapi alat yang Anda dapatkan di luar kotak dirancang untuk bekerja dengan sesuatu selain objek.
Data perl :: Dumper memungkinkan Anda untuk mengontrol seberapa dalam Anda ingin pergi, dan juga mendeteksi struktur yang ditautkan melingkar (itu benar-benar penting). Proses ini secara fundamental lebih mudah untuk dicapai dalam perl karena objek tidak memiliki sihir khusus di luar berkat mereka (proses yang didefinisikan secara universal).
Saya sarankan menggunakan 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__.
Dalam kebanyakan kasus, menggunakan __dict__
atau dir()
akan memberi Anda info yang Anda inginkan. Jika Anda membutuhkan lebih banyak detail, pustaka standar menyertakan modul inspect , yang memungkinkan Anda untuk mendapatkan sejumlah detail yang mengesankan. Beberapa saran nyata dari info termasuk:
Jika Anda hanya mencari "nilai atribut apa yang dimiliki objek saya?", Maka dir()
dan __dict__
mungkin cukup. Jika Anda benar-benar ingin menggali keadaan saat ini dari objek yang berubah-ubah (mengingat bahwa hampir semua objek adalah python), maka inspect
layak untuk dipertimbangkan.
Apakah ada fungsi bawaan untuk mencetak semua properti dan nilai saat ini dari suatu objek?
Tidak. Jawaban yang paling banyak dipilih tidak menyertakan beberapa atribut, dan jawaban yang diterima menunjukkan cara mendapatkan semua atribut, termasuk metode dan bagian dari api non-publik. Tapi tidak ada builtin lengkap yang bagus fungsi untuk ini.
Jadi akibat singkatnya adalah Anda bisa menulis sendiri, tetapi akan menghitung properti dan deskriptor data yang dihitung yang merupakan bagian dari API publik, dan Anda mungkin tidak menginginkan itu:
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))
Amati aplikasi jawaban terpilih saat ini di kelas dengan banyak jenis data anggota:
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))
hanya cetak:
{'baz': 'baz'}
Karena vars
hanya mengembalikan __dict__
objek, dan itu bukan salinan, jadi jika Anda memodifikasi dict yang dikembalikan oleh vars, Anda juga memodifikasi __dict__
objek itu sendiri.
vars(obj)['quux'] = 'WHAT?!'
vars(obj)
pengembalian:
{'baz': 'baz', 'quux': 'WHAT?!'}
- yang buruk karena quux adalah properti yang seharusnya tidak kita atur dan tidak boleh berada di namespace ...
Menerapkan saran dalam jawaban yang saat ini diterima (dan lainnya) tidak jauh lebih baik:
>>> 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']
Seperti yang dapat kita lihat, dir
hanya mengembalikan semua (sebenarnya hanya sebagian besar) dari nama yang terkait dengan objek.
inspect.getmembers
, disebutkan dalam komentar, juga cacat - mengembalikan semua nama dan nilai.
Saat mengajar, saya meminta siswa saya membuat fungsi yang menyediakan API objek semantik yang publik:
def api(obj):
return [name for name in dir(obj) if name[0] != '_']
Kita dapat memperluas ini untuk memberikan salinan namespace semantik dari suatu objek, tetapi kita perlu mengecualikan __slots__
yang tidak ditugaskan, dan jika kita menanggapi permintaan "properti saat ini" dengan serius, kita perlu mengecualikan properti yang dihitung (seperti mereka bisa menjadi mahal, dan bisa diartikan sebagai bukan "saat ini"):
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)}
Dan sekarang kami tidak menghitung atau menampilkan properti, quux:
>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}
Tapi mungkin kita tahu properti kita tidak mahal. Kami mungkin ingin mengubah logika untuk memasukkan mereka juga. Dan mungkin kami ingin mengecualikan deskriptor data khusus lainnya .
Maka kita perlu menyesuaikan fungsi ini lebih lanjut. Maka masuk akal bahwa kita tidak dapat memiliki fungsi bawaan yang secara ajaib tahu persis apa yang kita inginkan dan menyediakannya. Ini adalah fungsi yang perlu kita ciptakan sendiri.
Tidak ada fungsi bawaan yang melakukan ini, dan Anda harus melakukan apa yang paling semantik sesuai dengan situasi Anda.
FunctionType
. Tetapi sangat membantu - terima kasih!
Contoh metaprogramming objek Dump dengan sihir :
$ 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
Tanpa argumen:
$ python dump.py
<__main__.Data instance at 0x00A052D8>
Dengan Utilitas Gnosis :
$ 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>
Agak ketinggalan jaman tetapi masih berfungsi.
Jika Anda menggunakan ini untuk debugging, dan Anda hanya ingin dump rekursif dari semuanya, jawaban yang diterima tidak memuaskan karena mengharuskan kelas Anda sudah memiliki __str__
implementasi yang baik . Jika bukan itu masalahnya, ini bekerja lebih baik:
import json
print(json.dumps(YOUR_OBJECT,
default=lambda obj: vars(obj),
indent=1))
TypeError: vars() argument must have __dict__ attribute
Coba 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)
Keluaran:
__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)
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))
Ini mencetak semua konten objek secara rekursif dalam format indentasi json atau 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)
Saya telah mengangkat jawaban yang hanya menyebutkan sidik jari. Untuk menjadi jelas, jika Anda ingin melihat semua nilai dalam struktur data yang kompleks, maka lakukan sesuatu seperti:
from pprint import pprint
pprint(my_var)
Di mana my_var adalah variabel yang Anda minati. Ketika saya menggunakan, pprint(vars(my_var))
saya tidak mendapatkan apa-apa, dan jawaban lain di sini tidak membantu atau metode itu tampak terlalu lama. Ngomong-ngomong, dalam kasus khusus saya, kode yang saya periksa memiliki kamus kamus.
Layak menunjukkan bahwa dengan beberapa kelas khusus Anda mungkin berakhir dengan <someobject.ExampleClass object at 0x7f739267f400>
jenis output yang tidak membantu . Dalam hal ini, Anda mungkin harus menerapkan __str__
metode, atau mencoba beberapa solusi lain. Saya masih ingin menemukan sesuatu yang sederhana yang berfungsi di semua skenario, tanpa perpustakaan pihak ketiga.
Untuk membuang "myObject":
from bson import json_util
import json
print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))
Saya mencoba vars () dan dir (); keduanya gagal untuk apa yang saya cari. vars () tidak berfungsi karena objek tidak memiliki __dict__ (pengecualian .TypeError: vars () argumen harus memiliki atribut __dict__). dir () bukan yang saya cari: itu hanya daftar nama bidang, tidak memberikan nilai atau struktur objek.
Saya pikir json.dumps () akan bekerja untuk sebagian besar objek tanpa default = json_util.default, tetapi saya memiliki bidang datetime di objek sehingga serializer json gagal. Lihat Bagaimana mengatasi "datetime.datetime not JSON serializable" dengan python?
Mengapa bukan sesuatu yang sederhana:
for key,value in obj.__dict__.iteritems():
print key,value
for key,value in obj.__dict__.iteritems(): print key,value
?
pprint berisi "printer cantik" untuk menghasilkan representasi struktur data Anda yang menyenangkan secara estetis. Formatter menghasilkan representasi struktur data yang dapat diurai dengan benar oleh penerjemah, dan juga mudah bagi manusia untuk dibaca. Output disimpan pada satu baris, jika mungkin, dan menjorok ketika terbagi beberapa baris.
Coba cetak ulang .
Ini akan membantu Anda tidak hanya dengan mencetak variabel objek, tetapi juga output yang indah, seperti ini:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)
Untuk semua orang yang berjuang
vars()
tidak mengembalikan semua atribut. dir()
tidak mengembalikan nilai atribut.Kode berikut mencetak semua atribut obj
dengan nilainya:
for attr in dir(obj):
try:
print("obj.{} = {}".format(attr, getattr(obj, attr)))
except AttributeError:
print("obj.{} = ?".format(attr))
Anda dapat mencoba Flask Debug Toolbar.
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)
Ini berfungsi tidak masalah bagaimana variabel Anda didefinisikan di dalam kelas, di dalam __init__ atau di luar.
your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
__dict__
anggota (re.MatchObject
misalnya), tetapi builtindir()
berfungsi untuk semua objek.