是否有内置函数可以打印对象的所有当前属性和值?

Is there a built-in function to print all the current properties and values of an object?

提问人:fuentesjr 提问时间:10/11/2008 最后编辑:Communityfuentesjr 更新时间:10/8/2023 访问量:1282762

问:

所以我在这里寻找的是类似于 PHP 的 print_r 函数的东西。

这样我就可以通过查看相关对象的状态来调试我的脚本。

调试 内省 漂亮打印 python-datamodel

评论

2赞 Jonathan Scholbach 1/21/2021
你是在要求属性,不是吗?这个问题具有误导性,因为属性在 Python 中具有特定的含义,这与属性的含义不同。如果我是对的,也许你想改写你的问题?

答:

36赞 Joe Skora 10/11/2008 #1

您可以使用“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']
>>>

另一个有用的功能是帮助。

>>> 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
305赞 Dan Lenski 10/11/2008 #2
def dump(obj):
  for attr in dir(obj):
    print("obj.%s = %r" % (attr, getattr(obj, attr)))

有许多第三方函数可以根据作者的偏好添加异常处理、国家/特殊字符打印、递归到嵌套对象等。但它们基本上都归结为这一点。

评论

6赞 10/11/2008
unpythonic,因为遵循 not-invented-here
20赞 Dan Lenski 10/11/2008
说什么?当然,您可以使用标准模块中的函数,但我认为这会更有用,因为它说明了如何进行一般的内省。getmembers()inspect
27赞 Dan Lenski 10/11/2008
一点也不。dir(obj) 显示 (例如 和 ) 中未找到的属性。此外,对于用 声明的对象,它根本不起作用。通常,显示实际存储在字典内部的用户级属性。dir() 显示更多内容。__dict____doc____module____dict____slots____dict__
9赞 hobs 3/18/2012
某些类/对象不包含任何属性/成员。我知道这很疯狂,但这是真的。内置的 (如 和 或 s) 是常见的示例。尝试 ,然后尝试__dict__intstrre.MatchObject'hello'.__dict__dir('hello')
3赞 sdaau 11/11/2013
好吧,这个答案至少打印了属性的名称值,以防对象没有字典(比如返回,比如,),这就是我喜欢它的地方。QtGui.QMdiSubWindow.sizePolicy()
109赞 eduffy 10/11/2008 #3

dir已经提到过,但这只会给你属性的名称。如果您也想要它们的值,请尝试 .__dict__

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

o = O()

输出如下:

>>> o.__dict__

{'value': 3}

评论

12赞 anatoly techtonik 8/24/2015
像这样的对象没有,所以对于它们来说,它会失败set__dict__AttributeError: 'set' object has no attribute '__dict__'
803赞 user3850 10/11/2008 #4

你真的把两种不同的东西混在一起。

使用 dir()、vars()inspect 模块来获取您感兴趣的内容(我以此为例;您可以使用任何对象来代替)。__builtins__

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

随心所欲地打印字典:

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

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

漂亮的打印也可以在交互式调试器中作为命令使用:

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

评论

36赞 hobs 3/18/2012
令人惊讶的是,似乎并非所有对象都有成员(例如),但内置对象适用于所有对象。__dict__re.MatchObjectdir()
1赞 hobs 3/19/2012
print re.compile(r'slots').search('No slots here either.').__slots__
0赞 3/19/2012
@hobs:你知道“confer!”的意思是“另见”、“比较”吗?我知道匹配对象没有插槽。这不是我试图表达的重点。
7赞 Hai Phaikawl 5/22/2012
你为什么不在回答中多谈谈模块呢?我认为这是最接近print_r或var_dump的东西。inspect
1赞 HelloGoodbye 8/9/2019
那么,如何访问 列出的属性背后的值呢? 仅返回名称列表,并非所有名称都存在于属性中或属性中。dir()dir()vars()__dict__
1346赞 Jeremy Cantrell 10/11/2008 #5

你要与:vars()pprint()

from pprint import pprint
pprint(vars(your_object))

评论

46赞 12/19/2011
vars()只是返回其参数,这也是在没有方法的情况下的后备。所以首先使用,正如我所说。__dict__dir()__dir__dir()
39赞 Timmmm 8/1/2012
@hop:为您提供所有您可能不关心的内置内容,例如 和 。 不。dir()__str____new__var()
34赞 anatoly techtonik 8/24/2015
这在集合和其他没有属性的对象上失败。__dict__
2赞 joe-khoa 10/8/2020
这绝对是很好的 anwers,添加更多: from inspect import getmembers
12赞 cowlinator 3/4/2021
@hop,给出字段的值,同时使它们成为谜。vars()dir()
27赞 jfs 10/11/2008 #6

要打印对象的当前状态,您可以:

>>> obj # in an interpreter

print repr(obj) # in a script

print obj

对于您的类,定义或方法。来自 Python 文档__str____repr__

__repr__(self)由内置函数和字符串调用 转换(反向引号)到 计算“官方”字符串 对象的表示形式。如果有的话 可能,这应该看起来像一个 有效的 Python 表达式可以是 用于使用 相同的值(给定适当的 环境)。如果无法做到这一点, 格式为“<...一些有用的 描述。。。>“应返回。 返回值必须是字符串 对象。如果一个类定义了 repr() 但不是,那么是 也用于“非正式”字符串 该实例的表示形式 类是必需的。这通常是 用于调试,所以很重要 表示是 信息丰富且明确无误。repr()__str__()__repr__()

__str__(self)由内置函数和 print 调用 语句来计算 “informal” 对象的字符串表示形式。 这与以下不同 它不必是有效的 Python 表达方式:更方便或 可以使用简洁的表示 相反。返回值必须是 String 对象。str()__repr__()

评论

0赞 AlejandroVD 11/10/2015
此选项对于打印与对象内容连接的字符串非常有用:print "DEBUG: object value: " + repr(obj)
9赞 jfs 10/11/2008 #7

一个带有魔术的元编程示例 Dump 对象:

$ 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

不带参数:

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

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

它有点过时,但仍然有效。

15赞 William McVey 10/15/2008 #8

在大多数情况下,使用或将为您提供所需的信息。如果您碰巧需要更多详细信息,标准库包括 inspect 模块,它可以让您获得一些令人印象深刻的细节。一些真正的信息包括:__dict__dir()

  • 函数和方法参数的名称
  • 类层次结构
  • 函数/类对象实现的源代码
  • Frame 对象之外的局部变量

如果您只是在寻找“我的对象具有哪些属性值?”,那么 并且可能就足够了。如果你真的想深入研究任意对象的当前状态(请记住,在 python 中,几乎所有东西都是一个对象),那么值得考虑。dir()__dict__inspect

2赞 shahjapan 9/13/2010 #9

pprint 包含一个“漂亮的打印机”,用于生成美观的数据结构表示。格式化程序生成数据结构的表示形式,这些表示形式可以由解释器正确解析,并且也易于人类阅读。如果可能,输出将保留在一行上,并在拆分为多行时缩进。

20赞 Tel 11/15/2012 #10

可能值得一试——

是否有与 Perl 的 Data::D umper 等效的 Python?

我的建议是这样的——

https://gist.github.com/1071857

请注意,perl 有一个名为 Data::D umper 的模块,它将对象数据转换回 perl 源代码(注意:它不会将代码转换回源代码,而且几乎总是不希望输出中的对象方法函数)。这可用于持久性,但通常用于调试。

标准 python pprint 无法实现许多事情,特别是当它看到一个对象的实例并给你一个对象的内部十六进制指针时,它就会停止下降(呃,顺便说一句,那个指针并没有很多用处)。因此,简而言之,python 就是关于这个伟大的面向对象范式的,但你开箱即用的工具是为处理对象以外的东西而设计的。

perl Data::D umper 允许你控制你想去的深度,还可以检测圆形链接结构(这真的很重要)。从根本上说,这个过程在perl中更容易实现,因为对象除了祝福之外没有特别的魔力(一个普遍定义的过程)。

评论

2赞 memeplex 5/31/2016
> 所以简而言之,python 就是关于这个伟大的面向对象范式的,但你开箱即用的工具是为处理对象以外的东西而设计的......当您提供的唯一示例是次要的模块时,这是一个相当大的主张。
0赞 Peter Wood 10/8/2018
@memeplex 哪里说 python 是关于 OOP
0赞 Rainb 6/20/2020
这仅适用于 2.7
5赞 Michael Thamm 6/14/2013 #11

为什么不做一些简单的事情:

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

评论

0赞 Raz 10/30/2014
那不应该吗?for key,value in obj.__dict__.iteritems(): print key,value
0赞 Oleg 6/11/2022
不错,适合。但是修复了 params.__dict__.items() 中 key 和 value 的编译错误(可能是其他 Python 版本):print(key + “ = ” + str(value))
4赞 DaOneTwo 6/29/2013 #12

我需要在某些日志中打印 DEBUG 信息,但无法使用 pprint,因为它会破坏它。相反,我这样做了,得到了几乎同样的东西。

DO = DemoObject()

itemDir = DO.__dict__

for i in itemDir:
    print '{0}  :  {1}'.format(i, itemDir[i])
4赞 Clark 6/27/2014 #13

要转储“myObject”:

from bson import json_util
import json

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

我尝试了vars()和dir();两者都失败了,我无法满足我的要求。vars() 不起作用,因为该对象没有__dict__(异常。TypeError:vars() 参数必须具有__dict__属性)。dir() 不是我想要的:它只是一个字段名称列表,没有给出值或对象结构。

我认为json.dumps()适用于大多数没有default=json_util.default的对象,但是我在对象中有一个日期时间字段,因此标准json序列化程序失败了。请参阅如何克服python中的“datetime.datetime不可序列化”?

评论

1赞 Tim Ogilvy 4/16/2015
好的,是的,必须安装 pymongo tho 才能使用它。
7赞 32ndghost 7/14/2014 #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))
13赞 Adam Cath 11/24/2014 #15

如果你用它来调试,并且你只想要一个所有内容的递归转储,那么接受的答案是不令人满意的,因为它要求你的类已经有良好的实现。如果不是这种情况,这效果要好得多:__str__

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

评论

0赞 Tim Ogilvy 4/16/2015
这在 Python 3 上不起作用。必须安装 pymongo 并按照 @Clark 的回答进行操作
2赞 rob 10/1/2019
与这里的许多其他答案一样TypeError: vars() argument must have __dict__ attribute
8赞 wisbucky 3/5/2016 #16

这将以 json 或 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)
0赞 Slipstream 3/8/2016 #17

您可以尝试使用 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)
11赞 Symon 7/28/2016 #18

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

输出:

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

评论

0赞 Joseph Astrahan 2/17/2020
小提示添加 depth=6(或您需要的距离)作为它的参数之一,递归细节可以进一步:)。我喜欢它打印列表的一件事是它显示前 2 个完整条目和最后 2 个条目,因此您知道它正在工作
3赞 Anyany Pan 9/17/2016 #19

试试蜂纹

它不仅可以帮助您打印对象变量,还可以帮助您获得漂亮的输出,如下所示:

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

评论

1赞 Wavesailor 2/14/2019
该模块似乎不再维护,并且有许多未解决的问题。而是使用 ppretty
0赞 abulka 4/3/2023
beeprint 太冗长,无法弄清楚如何排除例如以 etc 开头的属性。没有很好的记录 - 或维护。_
-1赞 Evhz 5/4/2017 #20

我喜欢使用 python 对象内置类型、键

对于属性,无论它们是方法还是变量:

o.keys()

对于这些属性的值:

o.values()
3赞 Robert Hönig 9/7/2017 #21

对于每个苦苦挣扎的人

  • vars()不返回所有属性。
  • dir()不返回属性的值。

以下代码打印 的所有属性及其值:obj

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

评论

1赞 rob 10/1/2019
没有错误,但不是递归的,所以只是得到很多十六进制地址
5赞 Nagev 9/28/2017 #22

如果要查看复杂数据结构中的所有,请执行以下操作:

from pprint import pprint
pprint(my_var)

其中 my_var 是您感兴趣的变量。当我使用时,我一无所获,这里的其他答案也无济于事,或者该方法看起来不必要地长。顺便说一句,在我的特定情况下,我正在检查的代码有一本字典。pprint(vars(my_var))

值得指出的是,对于某些自定义类,您最终可能会得到一种无用的输出。在这种情况下,您可能需要实现一种方法,或尝试一些其他解决方案。<someobject.ExampleClass object at 0x7f739267f400>__str__

我还发现,在我得到这种类型的输出的一个例子中,向我展示了我想要的东西。因此,涵盖这两种情况的更好解决方案是单独尝试这两种情况。但是使用 有时会抛出异常,例如 .objectvars()vars()TypeError: vars() argument must have __dict__ attribute

我仍然想找到一些简单的东西,可以在所有情况下使用,而无需第三方库。

21赞 prosti 12/7/2018 #23

我建议使用 .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__.
78赞 Russia Must Remove Putin 12/2/2019 #24

是否有内置函数可以打印对象的所有当前属性和值?

不。投票最多的答案排除了某些类型的属性,而接受的答案显示了如何获取所有属性,包括非公共 API 的方法和部分。但是没有好的完整内置函数。

因此,简短的推论是,您可以编写自己的代码,但它将计算属性和其他计算的数据描述符,这些描述符是公共 API 的一部分,您可能不希望这样做:

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

其他答案的问题

观察当前投票最多的答案在具有许多不同类型数据成员的类上的应用:

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

仅打印:

{'baz': 'baz'}

因为返回一个对象,而且它不是副本,所以如果你修改了 vars 返回的字典,你也在修改对象本身的字典。vars__dict____dict__

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

返回:

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

-- 这很糟糕,因为 quux 是我们不应该设置的属性,也不应该在命名空间中......

应用当前接受的答案(和其他答案)中的建议也好不到哪里去:

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

正如我们所看到的,只返回与对象关联的所有(实际上只是大多数)名称。dir

inspect.getmembers,在评论中提到,也有类似的缺陷 - 它返回所有名称值。

从课堂上

在教学时,我让我的学生创建一个函数,该函数提供对象的语义公共 API:

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

我们可以扩展它以提供对象的语义命名空间的副本,但我们需要排除未分配的,如果我们认真对待对“当前属性”请求,我们需要排除计算属性(因为它们可能会变得昂贵,并且可以解释为不是“当前”):__slots__

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

现在我们不计算或显示属性 quux:

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

警告

但也许我们确实知道我们的房产并不昂贵。我们可能希望更改逻辑以包括它们。也许我们想排除其他自定义数据描述符。

然后我们需要进一步自定义这个函数。因此,我们不能有一个内置函数来神奇地确切地知道我们想要什么并提供它,这是有道理的。这是我们自己创造的功能。

结论

没有内置函数可以执行此操作,您应该执行语义上最适合您的情况的操作。

评论

0赞 NZD 8/22/2021
pypi.org/project/beeprint(或 github.com/panyanyany/beeprint)漂亮地打印“一切”,并且还递归打印。
0赞 Smart Manoj 9/21/2021
参数从函数中获取自定义内容的内容
0赞 Smart Manoj 9/21/2021
@NZD不适用于from collections import * ; obj=Counter([3,4])
5赞 Carl Cheung 2/3/2020 #25

无论您的变量在类内、__init__内或外如何定义,这都有效。

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

评论

1赞 Vladimir 11/6/2021
此外,要排除所有内置变量(方法、函数等):{attr: getattr(your_obj, attr) for attr in dir(your_obj) and "__" not in attr}
0赞 abulka 4/3/2023
@Vladimir,您的版本出现语法错误“”attr“未定义”
0赞 Vishnu 8/18/2021 #26

答案中,可以稍微修改一下,只获取对象的“属性”,如下所示:

def getAttributes(obj):
    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 for name in dir(obj) 
            if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)}
    pprint(attributes(obj))

在临时添加此函数时,它很有帮助,并且可以在不对现有源代码进行大量更改的情况下将其删除

1赞 MichaelMoser 9/15/2021 #27

这个项目修改了 pprint 以显示所有对象字段值,它忽略了对象成员函数,它还递归到嵌套对象中。它适用于 python3,参见 https://github.com/MoserMichael/pprintex 您可以通过 pip 安装它:__repr__pip install printex

2赞 Allohvk 10/4/2021 #28

虽然有很多好的答案,但这里有一个 1 行,可以给出属性和值:

(str(vars(config)).split(",")[1:])

其中 'config' 是有问题的对象。我将其列为单独的答案,因为我只想简单地打印对象的相关值(不包括__main等),而不使用循环或漂亮的打印,并且没有找到方便的答案。

1赞 yrnr 12/18/2021 #29

vars() 似乎显示了这个对象的属性,但 dir() 似乎也显示了父类的属性。您通常不需要查看继承的属性,例如 strdoc字典等。

In [1]: class Aaa():
...:     def __init__(self, name, age):
...:         self.name = name
...:         self.age = age
...:
In [2]: class Bbb(Aaa):
...:     def __init__(self, name, age, job):
...:         super().__init__(name, age)
...:         self.job = job
...:
In [3]: a = Aaa('Pullayya',42)

In [4]: b = Bbb('Yellayya',41,'Cop')

In [5]: vars(a)
Out[5]: {'name': 'Pullayya', 'age': 42}

In [6]: vars(b)
Out[6]: {'name': 'Yellayya', 'age': 41, 'job': 'Cop'}

In [7]: dir(a)
Out[7]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 ...
 ...
 '__subclasshook__',
 '__weakref__',
 'age',
 'name']
0赞 Timothy C. Quinn 10/12/2022 #30

我没有测试过性能,但我相信这是将 Python 中任何对象的属性/属性/键枚举为列表的最快方法。

# If core==False, ignore __k__ entries
def obj_props(obj, core=False) -> list:
    assert not obj is None, f"obj must not be null (None)"
    _props = []
    _use_dir=False
    def _add(p):
        if not core and p.find('__') == 0: return
        _props.append(p)
    if hasattr(obj, '__dict__'): 
        for p in obj.__dict__.keys(): _add(p)
    elif hasattr(obj, '__slots__'):
        for p in obj.__slots__: _add(p)
    elif hasattr(obj, 'keys'):
        try:
            for p in obj.keys(): _add(p)
        except Exception as ex:
            _props = []
            _use_dir = True
    else:
        _use_dir = True
    if _use_dir:
        # fall back to slow and steady
        for p in dir(obj):
            if not core and p.find('__') == 0: continue
            v = getattr(obj, p)
            v_t = type(v).__name__
            if v_t in ('function', 'method', 'builtin_function_or_method', 'method-wrapper'): continue
            _props.append(p)

    return _props

以上内容应该适用于常规的 python 对象 (with ),使用 slots () 的对象,甚至适用于类似字典的对象。__dict____slots__

大多数其他示例都利用了 which 将枚举对象的所有方法和属性,如果您只需要其属性,这些方法和属性将影响性能。dir(obj)

1赞 Ciro Santilli OurBigBook.com 4/20/2023 #31

@dataclass + pprint(递归、缩进、无外部库,Python 3.10)

@dataclass真是太棒了,从 Python 3.10 开始学习打印带有缩进的数据类,所以如果你能将你的代码转换为这是一个非常好的方法:pprint@dataclass

from dataclasses import dataclass
from pprint import pprint

@dataclass
class MyClass1:
    s: str
    n0: int
    n1: int
    n2: int
    n3: int
    n4: int
    n5: int
    n6: int
    n7: int
    n8: int
    n9: int

@dataclass
class MyClass2:
    s: str
    n0: int
    n1: int
    n2: int
    n3: int
    n4: int
    n5: int
    n6: int
    n7: int
    n8: int
    n9: int
    my_class_1: MyClass1

obj = MyClass2(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9, my_class_1=MyClass1(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9))
print(obj)
pprint(obj)

输出:

MyClass2(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9, my_class_1=MyClass1(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9))
MyClass2(s='a',
         n0=0,
         n1=1,
         n2=2,
         n3=3,
         n4=4,
         n5=5,
         n6=6,
         n7=7,
         n8=8,
         n9=9,
         my_class_1=MyClass1(s='a',
                             n0=0,
                             n1=1,
                             n2=2,
                             n3=3,
                             n4=4,
                             n5=5,
                             n6=6,
                             n7=7,
                             n8=8,
                             n9=9))

Смотритетакже: 漂亮的打印数据类更漂亮,带有换行符和缩进

@dataclass还免费为您提供其他非常好的功能:

与其他答案

让我们创建一个类似的非代码@dataclass

from pprint import pprint

class MyClass1:
    def __init__(self, s, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9):
        self.s = s
        self.n0 = n0
        self.n1 = n1
        self.n2 = n2
        self.n3 = n3
        self.n4 = n4
        self.n5 = n5
        self.n6 = n6
        self.n7 = n7
        self.n8 = n8
        self.n9 = n9

class MyClass2:
    def __init__(self, s, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, my_class_1):
        self.s = s
        self.n0 = n0
        self.n1 = n1
        self.n2 = n2
        self.n3 = n3
        self.n4 = n4
        self.n5 = n5
        self.n6 = n6
        self.n7 = n7
        self.n8 = n8
        self.n9 = n9
        self.n9 = n9
        self.my_class_1 = my_class_1

obj = MyClass2(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9, my_class_1=MyClass1(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9))
pprint(vars(obj))

pprint(vars(obj))输出是非递归的:

{'my_class_1': <__main__.MyClass1 object at 0x7fee21a9bf70>,
 'n0': 0,
 'n1': 1,
 'n2': 2,
 'n3': 3,
 'n4': 4,
 'n5': 5,
 'n6': 6,
 'n7': 7,
 'n8': 8,
 'n9': 9,
 's': 'a'}

在 Python 3.10.7、Ubuntu 22.10 上测试。

0赞 user966939 10/8/2023 #32

我想var_dump/print_r Selenium的浏览器状态,但是它的某些类属性并不总是实现/可访问的(取决于所使用的浏览器),这在某些情况下会导致异常。到目前为止,发布的解决方案似乎都无法解决该问题,因此我无法在崩溃之前转储所有属性。这是我能想出的唯一干净的解决方案:

import warnings

def dump(obj):
  for name in dir(obj):
    e = False
    with warnings.catch_warnings():
      warnings.simplefilter("ignore")
      try:
        v = getattr(obj, name)
      except:
        e = True
      warnings.simplefilter("default")
    if not e:
      print("obj.%s = %r" % (name, v))
    else:
      print("<inaccessible property obj.%s>" % name)

这还会禁止在访问属性时发出警告(例如弃用)。请注意,它不是递归的。