Câu trả lời:
Bạn đang thực sự pha trộn hai thứ khác nhau.
Sử dụng dir()
, vars()
hoặc các inspect
mô-đun để có được những gì bạn đang quan tâm (tôi sử dụng __builtins__
làm ví dụ, bạn có thể sử dụng bất kỳ đối tượng thay vì).
>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__
In từ điển đó tuy nhiên bạn thích:
>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...
hoặc là
>>> 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',
...
In đẹp cũng có sẵn trong trình gỡ lỗi tương tác như một lệnh:
(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ô-đun trong câu trả lời của bạn? Tôi nghĩ đó là thứ gần nhất với print_r hoặc var_dump.
dir()
, sau đó? dir()
chỉ trả về một danh sách các tên, và không phải tất cả những cái đó tồn tại trong vars()
hoặc trong __dict__
thuộc tính.
Bạn muốn vars()
trộn với pprint()
:
from pprint import pprint
pprint(vars(your_object))
vars()
chỉ đơn giản trả về __dict__
đối số của nó và đó cũng là dự phòng dir()
trong trường hợp không có __dir__
phương thức. Vì vậy, sử dụng dir()
ở nơi đầu tiên, như tôi đã nói.
dir()
cung cấp cho bạn tất cả những thứ được tích hợp trong những thứ mà bạn có thể không quan tâm __str__
và thích __new__
. var()
không.
__dict__
thuộc tính.
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
Có nhiều chức năng của bên thứ 3 ngoài đó có thêm các chức năng như xử lý ngoại lệ, in ký tự quốc gia / đặc biệt, đệ quy vào các đối tượng lồng nhau, v.v. theo sở thích của tác giả. Nhưng tất cả họ về cơ bản đun sôi xuống này.
getmembers()
chức năng trong inspect
mô-đun tiêu chuẩn , nhưng tôi nghĩ rằng điều này sẽ hữu ích hơn ở chỗ nó minh họa cách thực hiện nội quan nói chung.
__dict__
(như __doc__
và __module__
). Hơn nữa, __dict__
hoàn toàn không hoạt động đối với các đối tượng được khai báo __slots__
. Nói chung, __dict__
hiển thị các thuộc tính cấp người dùng thực sự được lưu trữ trong từ điển bên trong. dir () hiển thị nhiều hơn.
__dict__
thuộc tính / thành viên nào. Tôi biết điều đó thật điên rồ, nhưng sự thật. Tích hợp như int
và str
hoặc re.MatchObject
s là những ví dụ phổ biến. Hãy thử 'hello'.__dict__
, sau đó thửdir('hello')
dir đã được đề cập, nhưng nó sẽ chỉ cung cấp cho bạn tên của các thuộc tính. Nếu bạn muốn giá trị của chúng cũng hãy thử __dict__.
class O:
def __init__ (self):
self.value = 3
o = O()
Đây là đầu ra:
>>> o.__dict__
{'value': 3}
set
không có __dict__
, vì vậy đối với họ, nó sẽ thất bại vớiAttributeError: 'set' object has no attribute '__dict__'
Bạn có thể sử dụng hàm "dir ()" để làm điều này.
>>> 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']
>>>
Một tính năng hữu ích khác là trợ giúp.
>>> 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
Để in trạng thái hiện tại của đối tượng bạn có thể:
>>> obj # in an interpreter
hoặc là
print repr(obj) # in a script
hoặc là
print obj
Đối với các lớp của bạn định nghĩa __str__
hoặc __repr__
phương thức. Từ tài liệu Python :
__repr__(self)
Được gọi bởirepr()
hàm tích hợp và chuyển đổi chuỗi (dấu ngoặc kép) để tính toán biểu diễn chuỗi "chính thức" của một đối tượng. Nếu có thể, nó sẽ trông giống như một biểu thức Python hợp lệ có thể được sử dụng để tạo lại một đối tượng có cùng giá trị (được cung cấp một môi trường thích hợp). Nếu điều này là không thể, một chuỗi có dạng "<... một số mô tả hữu ích ...>" sẽ được trả về. Giá trị trả về phải là một đối tượng chuỗi. Nếu một lớp định nghĩa repr () nhưng không__str__()
, thì__repr__()
cũng được sử dụng khi biểu diễn chuỗi "không chính thức" của các thể hiện của lớp đó là bắt buộc. Điều này thường được sử dụng để gỡ lỗi, vì vậy điều quan trọng là đại diện phải giàu thông tin và không rõ ràng.
__str__(self)
Được gọi bởi hàmstr()
dựng sẵn và bằng câu lệnh in để tính toán biểu diễn chuỗi "không chính thức" của một đối tượng. Điều này khác__repr__()
ở chỗ nó không phải là một biểu thức Python hợp lệ: thay vào đó có thể sử dụng một biểu diễn thuận tiện hoặc ngắn gọn hơn. Giá trị trả về phải là một đối tượng chuỗi.
print "DEBUG: object value: " + repr(obj)
Có thể đáng để kiểm tra -
Có Python tương đương với Dữ liệu của Perl :: Dumper không?
Đề nghị của tôi là thế này -
https://gist.github.com/1071857
Lưu ý rằng perl có một mô-đun gọi là Data :: Dumper giúp dịch dữ liệu đối tượng trở lại mã nguồn perl (NB: nó không dịch mã trở lại nguồn và hầu như bạn luôn không muốn các hàm phương thức đối tượng trong đầu ra). Điều này có thể được sử dụng để kiên trì, nhưng mục đích chung là để gỡ lỗi.
Có một số điều mà pprint python tiêu chuẩn không đạt được, đặc biệt là nó chỉ dừng lại khi nó nhìn thấy một thể hiện của một đối tượng và cung cấp cho bạn con trỏ hex bên trong của đối tượng (errr, con trỏ đó không được sử dụng nhiều bởi cách). Vì vậy, tóm lại, python là tất cả về mô hình hướng đối tượng tuyệt vời này, nhưng các công cụ bạn lấy ra khỏi hộp được thiết kế để làm việc với một cái gì đó không phải là các đối tượng.
Dữ liệu perl :: Dumper cho phép bạn kiểm soát mức độ bạn muốn đi sâu và cũng phát hiện các cấu trúc được liên kết tròn (điều đó thực sự quan trọng). Quá trình này về cơ bản dễ dàng đạt được hơn trong perl vì các đối tượng không có phép thuật đặc biệt nào ngoài phước lành của họ (một quy trình được xác định rõ ràng trên toàn cầu).
Tôi khuyên bạn nên sử dụng 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__.
Trong hầu hết các trường hợp, sử dụng __dict__
hoặc dir()
sẽ giúp bạn có được thông tin bạn muốn. Nếu bạn cần thêm chi tiết, thư viện tiêu chuẩn bao gồm mô-đun kiểm tra , cho phép bạn có được một số lượng chi tiết ấn tượng. Một số đề xuất thực sự của thông tin bao gồm:
Nếu bạn chỉ tìm kiếm "những gì giá trị thuộc tính không đối tượng của tôi có?", Sau đó dir()
và __dict__
có lẽ là đủ. Nếu bạn thực sự muốn tìm hiểu về trạng thái hiện tại của các đối tượng tùy ý (hãy nhớ rằng trong python hầu hết mọi thứ đều là một đối tượng), thì inspect
đáng để xem xét.
Có một chức năng tích hợp để in tất cả các thuộc tính và giá trị hiện tại của một đối tượng không?
Không. Câu trả lời được đánh giá cao nhất loại trừ một số loại thuộc tính và câu trả lời được chấp nhận cho biết cách nhận tất cả các thuộc tính, bao gồm các phương thức và các phần của api không công khai. Nhưng không có nội dung hoàn chỉnh tốt chức năng cho việc này.
Vì vậy, hệ quả tất yếu là bạn có thể tự viết, nhưng nó sẽ tính toán các thuộc tính và các mô tả dữ liệu được tính toán khác là một phần của API công khai và bạn có thể không muốn điều đó:
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))
Quan sát ứng dụng của câu trả lời được bình chọn hàng đầu hiện nay trên một lớp với rất nhiều loại thành viên dữ liệu khác nhau:
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))
chỉ in:
{'baz': 'baz'}
Bởi vì vars
chỉ trả về __dict__
đối tượng và nó không phải là bản sao, vì vậy nếu bạn sửa đổi lệnh được trả về bởi vars, bạn cũng sẽ sửa đổi __dict__
chính đối tượng đó.
vars(obj)['quux'] = 'WHAT?!'
vars(obj)
trả về:
{'baz': 'baz', 'quux': 'WHAT?!'}
- đó là xấu vì quux là một thuộc tính mà chúng ta không nên đặt và không nên ở trong không gian tên ...
Áp dụng lời khuyên trong câu trả lời hiện được chấp nhận (và những người khác) không tốt hơn nhiều:
>>> 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']
Như chúng ta có thể thấy, dir
chỉ trả về tất cả (thực tế chỉ là hầu hết) các tên được liên kết với một đối tượng.
inspect.getmembers
, được đề cập trong các ý kiến, là thiếu sót tương tự - nó trả về tất cả các tên và giá trị.
Khi giảng dạy, các sinh viên của tôi tạo ra một hàm cung cấp API công khai về mặt ngữ nghĩa của một đối tượng:
def api(obj):
return [name for name in dir(obj) if name[0] != '_']
Chúng ta có thể mở rộng điều này để cung cấp một bản sao của không gian tên ngữ nghĩa của một đối tượng, nhưng chúng ta cần loại trừ __slots__
không được gán và nếu chúng ta thực hiện nghiêm túc yêu cầu "thuộc tính hiện tại", chúng ta cần loại trừ các thuộc tính được tính toán (như chúng có thể trở nên đắt đỏ và có thể được hiểu là không "hiện tại"):
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)}
Và bây giờ chúng tôi không tính toán hoặc hiển thị tài sản, quux:
>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}
Nhưng có lẽ chúng ta biết tài sản của mình không đắt. Chúng tôi có thể muốn thay đổi logic để bao gồm chúng là tốt. Và có lẽ chúng tôi muốn loại trừ các mô tả dữ liệu tùy chỉnh khác thay thế.
Sau đó, chúng ta cần tùy chỉnh thêm chức năng này. Và do đó, điều hợp lý là chúng ta không thể có một chức năng tích hợp có thể biết chính xác những gì chúng ta muốn và cung cấp nó. Đây là chức năng chúng ta cần tạo ra chính mình.
Không có chức năng tích hợp nào thực hiện điều này và bạn nên làm những gì phù hợp nhất về mặt ngữ nghĩa cho tình huống của bạn.
FunctionType
. Nhưng rất hữu ích - cảm ơn!
Một ví dụ siêu lập trình đối tượng Dump với phép thuật :
$ 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
Không có đối số:
$ python dump.py
<__main__.Data instance at 0x00A052D8>
Với sử dụng Gnosis :
$ python dump.txt 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>
Nó hơi lỗi thời nhưng vẫn hoạt động.
Nếu bạn đang sử dụng điều này để gỡ lỗi và bạn chỉ muốn kết xuất đệ quy mọi thứ, câu trả lời được chấp nhận là không thỏa mãn vì nó yêu cầu các lớp của bạn đã __str__
triển khai tốt . Nếu đó không phải là trường hợp, điều này hoạt động tốt hơn nhiều:
import json
print(json.dumps(YOUR_OBJECT,
default=lambda obj: vars(obj),
indent=1))
TypeError: vars() argument must have __dict__ attribute
thử 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)
Đầu ra:
__main__.A(_p = 8, foo = [0, 1, ..., 8, 9], s = 5)
Điều này in ra tất cả các nội dung đối tượng đệ quy ở định dạng thụt lề json hoặc 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)
Tôi đã đưa ra câu trả lời chỉ đề cập đến dấu ấn. Để rõ ràng, nếu bạn muốn xem tất cả các giá trị trong cấu trúc dữ liệu phức tạp, thì hãy làm một cái gì đó như:
from pprint import pprint
pprint(my_var)
Trong đó my_var là biến quan tâm của bạn. Khi tôi sử dụng, pprint(vars(my_var))
tôi không nhận được gì, và các câu trả lời khác ở đây không giúp được gì hoặc phương pháp này trông có vẻ không cần thiết. Nhân tiện, trong trường hợp cụ thể của tôi, mã tôi đang kiểm tra có một từ điển từ điển.
Đáng để chỉ ra rằng với một số lớp tùy chỉnh, bạn có thể kết thúc với một <someobject.ExampleClass object at 0x7f739267f400>
loại đầu ra không có ích . Trong trường hợp đó, bạn có thể phải thực hiện một __str__
phương pháp hoặc thử một số giải pháp khác. Tôi vẫn muốn tìm một cái gì đó đơn giản hoạt động trong tất cả các kịch bản, không có thư viện của bên thứ ba.
Để kết xuất "myObject":
from bson import json_util
import json
print(json.dumps(myObject, default=json_util.default, sort_keys=True, indent=4, separators=(',', ': ')))
Tôi đã thử vars () và dir (); cả hai đều thất bại cho những gì tôi đang tìm kiếm. vars () không hoạt động vì đối tượng không có __dict__ (ngoại lệ.TypeError: vars () đối số phải có thuộc tính __dict__). dir () không phải là thứ tôi đang tìm kiếm: nó chỉ là một danh sách các tên trường, không đưa ra các giá trị hoặc cấu trúc đối tượng.
Tôi nghĩ rằng json.dumps () sẽ hoạt động cho hầu hết các đối tượng mà không có default = json_util.default, nhưng tôi đã có trường datetime trong đối tượng nên trình tuần tự json chuẩn không thành công. Xem Cách khắc phục "datetime.datetime không JSON serializable" trong python?
Tại sao không phải là một cái gì đó đơn giản:
for key,value in obj.__dict__.iteritems():
print key,value
for key,value in obj.__dict__.iteritems(): print key,value
vậy không?
pprint chứa một máy in khá đẹp mắt, dùng để tạo các biểu diễn thẩm mỹ cho cấu trúc dữ liệu của bạn. Trình định dạng tạo ra các biểu diễn cấu trúc dữ liệu có thể được phân tích cú pháp chính xác bởi trình thông dịch và cũng dễ dàng cho người đọc. Đầu ra được giữ trên một dòng, nếu có thể và thụt lề khi chia thành nhiều dòng.
Chỉ cần thử bíp .
Nó sẽ giúp bạn không chỉ với việc in các biến đối tượng, mà cả đầu ra đẹp, như thế này:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)
Cho mọi người đấu tranh với
vars()
không trả lại tất cả các thuộc tính. dir()
không trả về giá trị của các thuộc tính.Đoạn mã sau in tất cả các thuộc tính của obj
với các giá trị của chúng:
for attr in dir(obj):
try:
print("obj.{} = {}".format(attr, getattr(obj, attr)))
except AttributeError:
print("obj.{} = ?".format(attr))
Bạn có thể thử Thanh công cụ gỡ lỗi 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)
Tôi thích làm việc với các loại khóa hoặc giá trị của đối tượng python .
Đối với các thuộc tính bất kể chúng là phương thức hay biến:
o.keys()
Đối với các giá trị của các thuộc tính đó:
o.values()
Điều này hoạt động bất kể các varibles của bạn được định nghĩa như thế nào trong một lớp, bên trong __init__ hoặc bên ngoài.
your_obj = YourObj()
attrs_with_value = {attr: getattr(your_obj, attr) for attr in dir(your_obj)}
__dict__
thành viên (re.MatchObject
ví dụ), nhưng dựng sẵndir()
hoạt động cho tất cả các đối tượng.