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

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


当前回答

您可以尝试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)

其他回答

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

不。投票最多的答案排除了某些类型的属性,而接受的答案显示了如何获取所有属性,包括方法和部分非公共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': ''}

警告

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

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

结论

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

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

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

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

一个有魔力的元编程示例转储对象:

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

虽然有点过时,但还能用。

从答案中,可以稍微修改一下,只得到一个对象的“Attributes”,如下所示:

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

在临时添加此函数时非常有用,并且可以在不修改现有源代码的情况下删除此函数

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

>>> obj # in an interpreter

or

print repr(obj) # in a script

or

print obj

为你的类定义__str__或__repr__方法。来自Python文档:

__repr__(self)由repr()内置函数调用,由字符串调用 转换(反引号)到 计算“官方”字符串 对象的表示。如果有的话 可能,这看起来像a 有效的Python表达式 方法重新创建对象 相同的值(给定一个合适的 环境)。如果不可能, 形式为“<…一些有用的 描述……应该返回>。 返回值必须为字符串 对象。如果一个类定义了repr() 但不是__str__(),则__repr__()是 也用于“非正式”字符串 实例的表示 班级是必需的。这是典型的 用于调试,所以很重要 这个表示是 信息丰富且明确。 __str__(self)由str()内置函数调用,由print函数调用 语句来计算“非正式的” 对象的字符串表示形式。 这与__repr__()不同 它不必是一个有效的Python 表达:比较方便还是 可以使用简洁的表示 代替。返回值必须为a 字符串对象。