Итерации над объектами "общедоступные" атрибуты

В последнее время я нахожу, что пишу код следующим образом:

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

Есть ли более питонический способ доступа к объекту "общедоступное" пространство имен?

Ответ 1

Вы можете подготовить список "общедоступных" атрибутов (как список или генератор) до:

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

Но, пожалуйста, прочитайте примечание о функции dir() в документации:

Примечание Поскольку dir() предоставляется в основном как удобство для использования в интерактивном приглашении, он пытается предоставить интересный набор имен больше, чем пытается обеспечить строго или последовательно определенный набор имена и подробное поведение могут меняться в разных версиях. Например, атрибуты metaclass не входят в список результатов, когда аргумент является классом.

Вы также должны знать, что любой класс может реализовать метод __dir__(), который может возвращать список имен, которые не обязательно соответствуют именам атрибутов. Другими словами, dir(something) не гарантирует, что результат вернет атрибуты something.

Ответ 2

Вместо этого вы можете использовать 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'}

Заметим, что, как отметил Никлас Р, переменные с одним символом подчеркивания также считаются частными. Однако функция vars() имеет то преимущество, что исключает все переменные экземпляра.

Ответ 3

Я чувствую, что итерация над пониманием списка немного более питонична, чем использование ключевого слова continue, но это может быть просто вопросом вкуса. Это, по общему признанию, не намного элегантнее того, что у вас уже есть.

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

Примечание. Отдельные атрибуты подчеркивания также не являются "общедоступными".