Python: элементы класса ENUM недоступны для встроенной функции dir () - PullRequest
2 голосов
/ 12 июня 2019

Я пытаюсь получить переменные класса ENUM , используя встроенный dir .Для обычного класса мы получаем следующий результат:

from enum import Enum
class foo(Enum):
    a = 1
    b = 2
    c = 3

>>> dir(foo)
['__class__', '__doc__', '__members__', '__module__', 'a', 'b', 'c']

Но если я немного подправлю этот класс, чтобы получить значения словаря, используя оператор точки, как показано ниже,

class foo(Enum):
    class DotDict(dict):
        # Use this to access the dictionary elements using dot notation
        def __getattr__(*args):
            val = dict.get(*args)
            return DotDict(val) if type(val) is dict else val
        __setattr__ = dict.__setitem__
        __delattr__ = dict.__delitem__

    # class variables
    a = DotDict({'index': 1, 'city': {'name': 'NY', 'len': 2}})
    b = DotDict({'index': 2, 'city': {'name': 'London', 'len': 6}})
    c = DotDict({'index': 3, 'city': {'name': 'Delhi', 'len': 5}})

, я получу следующеерезультат без включенной переменной класса,

>>> dir(foo)
['DotDict', '__class__', '__doc__', '__members__', '__module__']

Одна странная вещь здесь, я все еще могу получить доступ к переменным класса, как показано ниже,

>>> foo.a.index
1

>>> foo.b.city.name
London

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

1 Ответ

2 голосов
/ 12 июня 2019

Где-то в начале 3.x строки dir() стал реализуемым в качестве метода __dir__ для класса, и Enum использует это для отображения только четырех атрибутов __xxx__ и любых членов.

Причина, по которой a, b и c не отображаются в dir(foo), заключается в том, что они не являются членами и не являются членами, поскольку DotDict.__getattr__() не работает.

Соответствующий ответ от __getattr__ для отсутствующих атрибутов вызывает AttributeError, но вместо этого вы возвращаете экземпляр DotDict и имя поиска, что можно увидеть, когда добавляется print():

>>> a.__get__
({'a': 1}, '__get__')

Это важно, поскольку дескрипторы не преобразуются в члены, и наличие __get__, __set__ или __delete__ указывает на дескриптор.


TL; DR

Исправьте __getattr__ и все должно работать как положено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...