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

230
dir(re.compile(pattern)) 

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

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

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

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

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

Список не обязательно завершен.

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

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

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

Бартош Радачинский
источник
5
использование dir()или проверка модуля, как правило, является правильным способом сделать это. Вы использовали reмодуль просто в качестве примера или хотите достичь особой цели?
1
Вы уверены, что шаблон фактически сохраняется как данные после компиляции? У меня сложилось впечатление, что целью компиляции шаблона было создание автоматов конечного состояния, необходимых для анализа данного шаблона.
Кайл Стрэнд,
@hop не может обходиться без классов? Например, они могут сделать их на__dir__()
ytpillai
ytpillai: правильно, но только в Python 3. Тем не менее, вопрос в том, подпадает ли такой класс под «общий случай»

Ответы:

140

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

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

PierreBdR
источник
1
inpect.getmembers (re.compile (pattern)) также не выдает pattern в качестве члена, поэтому он, вероятно, использует dir для внутреннего использования ... Это отстой!
Бартош Радачинский
Я также мог бы использовать callable, чтобы проверить, являются ли они методами, но это не главное ... Дело в том, что я не могу доверять dir, чтобы он возвращал даже список атрибутов, которые на самом деле публично видны ...
Bartosz Radaczyński
2
inspect должен быть «по крайней мере таким же» заслуживающим доверия, как dir (). с другой стороны, re - очень сложный модуль
Что вы определяете как «публично видимый»? Если вы имеете в виду «можно получить доступ», то по указанной причине это потерянное дело. В противном случае, 'dir' всегда возвращает список атрибутов, доступных в стандартной реализации getattr.
PierreBdR
2
dir (my_class) возвращает что-то отличное от my_class .__ dict __. keys (). первый также выводит методы класса, такие как init и doc
JuanPi
58

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

видеть:

Моу
источник
Я получаю эту ошибку: >> dir __ (pyrenderdoc) Traceback (последний вызов был последним): файл "<string>", строка 1, в <module> NameError: имя '__dir ' не определено
Мона Джалал,
__dir__ () - это метод объекта, а не функция - пожалуйста, прочитайте ссылки в ответе, и это
Мо
Одна строчка, чтобы распечатать все атрибуты и их значения:pprint({k:getattr(ojb,k) for k in obj.__dir__()})
Czechchnology
21

Вот практическое дополнение к ответам 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__атрибут) .

ジ ョ ー ジ
источник
9

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

  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)

    TypeError: дескриптор __dir__из 'object'объекта нужен аргумент

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

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

Chiron
источник
5

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

Данный объект создан с помощью 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}
mluc
источник
список всех атрибутов в Python 3.x: {. ключ: значение для ключа, значение в OBJ .__ ДИКТ __ элементы () , если не key.startswith ( "__")} [ '_'] declared_fields клавиши ().
above_c_level