关于python:迭代对象的“公共”属性

Iterate over an object's “public” attributes

本问题已经有最佳答案,请猛点这里访问。

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

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

是否有一种更为python的方式来访问对象的"public"名称空间?


您可以使用vars函数来代替。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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()函数具有消除除实例变量以外的所有变量的优点。


您可以先准备"公共"属性列表(作为列表或生成器):

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

但请阅读文档中有关dir()功能的说明:

Note Because dir() is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases. For example, metaclass attributes are not in the result list when the argument is a class.

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


我觉得重复列表理解比使用continue关键字要略胜一筹,但这可能只是一个品味问题。诚然,它并不比你已经拥有的更优雅。

1
2
for attr in (a for a in dir(object) if not a.startswith('_')):
  pass

注意:单个下划线属性也不是"public"。