Как получить полный список методов и атрибутов объекта? - PullRequest
212 голосов
/ 10 октября 2008
dir(re.compile(pattern)) 

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

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

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

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

Также сказано, что

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

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

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

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

Ответы [ 5 ]

135 голосов
/ 10 октября 2008

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

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

53 голосов
/ 10 октября 2008

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

см

19 голосов
/ 25 апреля 2012

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

7 голосов
/ 17 октября 2018

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

  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. Если вы хотите, чтобы надежная схема пересекала все атрибуты объекта, помните, что каждый питонический стандарт может быть переопределен и может не содержать , и каждое соглашение может быть ненадежным.

4 голосов
/ 02 сентября 2016

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

Учитывая объект, созданный с помощью 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}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...