遍历对象的“公共”属性 [duplicate]

Iterate over an object's "public" attributes [duplicate]

提问人:William Pursell 提问时间:1/20/2012 更新时间:7/12/2022 访问量:18776

问:

最近,我发现自己在写这样的代码:

for name in dir( object ):
    if name.startswith( '__' ) : continue
    ...

有没有一种更 pythonic 的方式来访问对象的“公共”命名空间?

评论

2赞 SingleNegationElimination 1/20/2012
你首先要解决什么问题,这个结构是有用的?
0赞 Niklas R 1/20/2012
怎么样?请注意,在 Python 中,即使是一个下划线 () 也是为了表示“私有”属性。for name in filter( lambda x: not x.startswith('_'), dir(obj)):_
2赞 Dan D. 1/20/2012
@NiklasR不需要过滤器for name in ( x for x in dir(obj) if not x.startswith('_') ):
0赞 William Pursell 11/10/2017
奇怪的是,这个问题被标记为 6 个月后提出的问题的重复......
1赞 William Pursell 11/10/2017
同样奇怪的是,这是在提出问题 5 年后发生的!

答:

22赞 srgerg 1/20/2012 #1

您可以改用 vars 函数

例如:

>>> class C(object):
...   def __init__(self):
...     self.__foo = 'foo'
... 
>>> c = C()
>>> dir(c)
['_C__foo', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__',    
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',    
'__weakref__']
>>> vars(c)
{'_C__foo': 'foo'}

请注意,正如 Niklas R 所指出的,带有单个下划线的变量也被视为私有变量。但是,该函数的优点是消除了除实例变量之外的所有变量。vars()

评论

2赞 wim 1/20/2012
我在其他一些物体上尝试这个时得到TypeError: vars() argument must have __dict__ attribute
3赞 srgerg 1/20/2012
是的,该函数只能用于具有 .因此,例如,如果在类上定义了 Force,则无法使用该函数。vars()__dict____slots__vars()
2赞 Joe Kington 1/20/2012
还要注意的是,这不会得到任何属性,所以不仅仅是那些不起作用的东西。__slots__
2赞 wim 1/20/2012 #2

与使用关键字的排除分支相比,直接迭代对公共名称的理解似乎更像是 Pythonic。但这可能只是一个品味问题,诚然,它并不比你已经拥有的好多少。continue

public_names = (n for n in dir(object) if not n.startswith('_'))
for attr in public_names:
    ...

注意:单个下划线属性也不是“公共”属性。

19赞 Tadeck 1/20/2012 #3

您可以在以下情况下准备“public”属性列表(作为列表或生成器):

>>> public_props = (name for name in dir(object) if not name.startswith('_'))
>>> for name in public_props:
    print name

但请阅读文档中有关函数的注释:dir()

注意由于提供它主要是为了方便在交互式提示下使用,因此它尝试提供一组有趣的名称,而不是尝试提供一组严格或一致定义的名称,并且其详细行为可能会因版本而异。例如,当参数是类时,元类属性不在结果列表中。dir()

您还应该知道,任何类都可以实现可能返回不一定与属性名称对应的名称列表的方法。换言之,不保证结果将返回 的属性。__dir__()dir(something)something

评论

1赞 Dave 4/15/2015
有没有理由更喜欢?dir(object)object.__dict__
1赞 James Lin 6/1/2016
object.__dict__不一定返回您想要的属性,至少从我的测试结果来看是这样。