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

dir(re.compile(pattern)) 

не возвращает шаблон как один из элементов списков. А именно это возвращает:

['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn']

Согласно инструкции, он должен содержать

имена атрибутов объекта, имена атрибутов его класса и рекурсивные атрибуты базовых классов его класса.

Это также говорит о том, что

Список не обязательно полный.

Есть ли способ получить полный список? Я всегда предполагал, что dir возвращает полный список, но, видимо, это не так...

Также: есть ли способ перечислить только атрибуты? Или только методы?

Изменить: это на самом деле ошибка в Python -> предположительно это исправлено в ветке 3.0 (и, возможно, также в 2.6)

5 ответов

Решение

Для полного списка атрибутов, краткий ответ: нет. Проблема в том, что атрибуты фактически определяются как аргументы, принятые getattr встроенная функция. Как пользователь может переопределить __getattr__Внезапно разрешая любой вид атрибута, нет никакого общего способа создать этот список. dir функция возвращает ключи в __dict__ атрибут, т.е. все атрибуты, доступные, если __getattr__ метод не реализован.

По второму вопросу это не имеет смысла. На самом деле, методы являются вызываемыми атрибутами, не более того. Вы можете фильтровать вызываемые атрибуты и, используя inspect Модуль определения класса методов, методов или функций.

Вот почему новый __dir__() метод был добавлен в Python 2.6

увидеть:

Вот практическое дополнение к ответам PierreBdR и Мо:

- для Python >= 2.6 и классов нового стиля, dir() кажется достаточным;
- для классов старого стиля мы можем, по крайней мере, сделать то, что делает стандартный модуль для поддержки завершения табуляции: в дополнение к dir(), Ищу __class__ - а потом пойти на свою __bases__:

# code borrowed from the rlcompleter module
# tested under Python 2.6 ( sys.version = '2.6.5 (r265:79063, Apr 16 2010, 13:09:56) \n[GCC 4.4.3]' )

# or: from rlcompleter import get_class_members
def get_class_members(klass):
    ret = dir(klass)
    if hasattr(klass,'__bases__'):
        for base in klass.__bases__:
            ret = ret + get_class_members(base)
    return ret


def uniq( seq ): 
    """ the 'set()' way ( use dict when there's no set ) """
    return list(set(seq))


def get_object_attrs( obj ):
    # code borrowed from the rlcompleter module ( see the code for Completer::attr_matches() )
    ret = dir( obj )
    ## if "__builtins__" in ret:
    ##    ret.remove("__builtins__")

    if hasattr( obj, '__class__'):
        ret.append('__class__')
        ret.extend( get_class_members(obj.__class__) )

        ret = uniq( ret )

    return ret

(Тестовый код и выходные данные для краткости удалены, но в основном для объектов нового стиля мы, похоже, получаем те же результаты для get_object_attrs() что касается dir()и для классов старого стиля главное дополнение к dir() выход, кажется, __class__ атрибут))

Только для дополнения:

  1. dir() это самый мощный / фундаментальный инструмент. [Наиболее рекомендуется]
  2. Решения кроме dir() просто предоставить свой способ борьбы с выходом dir(),
    Перечислять атрибуты 2-го уровня или нет, важно сделать просеивание самостоятельно,
    потому что иногда вы можете захотеть отсеять внутренние переменные с подчеркиванием __
    но иногда вам может понадобиться __doc__ док-строка.
  3. __dir__() а также dir() возвращает идентичный контент.
  4. __dict__ а также dir() разные. __dict__ возвращает неполное содержание.
  5. ВАЖНО: __dir__() иногда может быть переписан автором для какой-либо цели с помощью функции, значения или типа. Вот пример:
    \\...\\torchfun.py in traverse(self, mod, search_attributes) 445 if prefix in traversed_mod_names: 446 continue 447 names = dir(m) 448 for name in names: 449 obj = getattr(m,name) Ошибка типа: дескриптор __dir__ из 'object' объект нуждается в аргументе

    Автор pyTorch изменил __dir__() метод к чему-то, что требует аргумента. Эта модификация делает dir() потерпеть поражение.

  6. Если вы хотите, чтобы надежная схема пересекала все атрибуты объекта, помните, что каждый питонический стандарт может быть переопределен и может не выполняться, а каждое соглашение может быть ненадежным.

Вот как я это делаю, полезно для простых пользовательских объектов, к которым вы продолжаете добавлять атрибуты:

Данный объект создан с obj = type("Obj",(object,),{})или просто:

class Obj: pass
obj = Obj()

Добавьте некоторые атрибуты:

obj.name = 'gary'
obj.age = 32

затем, чтобы получить словарь только с пользовательскими атрибутами:

{key: value for key, value in obj.__dict__.items() if not key.startswith("__")}

# {'name': 'gary', 'age': 32}
Другие вопросы по тегам