是否有一个内置函数可以打印对象的所有当前属性和值?
没有。投票最多的答案排除了某些类型的属性,接受的答案显示了如何获取 all 属性,包括非公共 api 的方法和部分。但是没有很好的完整的 builtin 功能。
所以简短的推论是您可以编写自己的,但它会计算属于公共 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 只返回所有(实际上只是大多数)与对象关联的名称。
在 cmets 中提到的
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': ''}
注意事项
但也许我们确实知道我们的房产并不昂贵。我们可能想要更改逻辑以包含它们。也许我们想排除 other custom 数据描述符。
那么我们需要进一步定制这个功能。因此,我们不能拥有一个神奇地知道我们想要什么并提供它的内置函数是有道理的。这是我们需要自己创建的功能。
结论
没有执行此操作的内置函数,您应该根据您的情况执行最符合语义的操作。