这里我要找的是PHP的print_r函数。

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


当前回答

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

其他回答

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

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

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

你实际上是把两种不同的东西混合在一起。

使用dir(), vars()或inspect模块来获取您感兴趣的内容(我使用__builtins__作为示例;你可以用任何物体代替)。

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

随你喜欢,把那本词典打印出来吧:

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

or

>>> 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 print也可以在交互式调试器中作为命令使用:

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

Vars()似乎显示了该对象的属性,但dir()似乎也显示了父类(es)的属性。您通常不需要看到继承的属性,如str, doc。dict等等。

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

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

对于属性,不管它们是方法还是变量:

o.keys()

对于这些属性的值:

o.values()

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

不。投票最多的答案排除了某些类型的属性,而接受的答案显示了如何获取所有属性,包括方法和部分非公共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只返回对象的__dict__,而且它不是一个副本,所以如果你修改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只返回与对象相关的所有(实际上是大部分)名称。

检查。评论中提到的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': ''}

警告

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

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

结论

没有内置函数可以做到这一点,您应该根据自己的情况选择语义上最合适的方法。