#python #enums
Вопрос:
Я просто хочу добиться некоторого дополнительного, чего нет в операторном модуле python not_contain
. Для этого я создал свой собственный класс с not_contain
помощью метода. Я просто хочу сделать еще несколько вариаций, и для этого мне нужен класс. Я использую python3.
class UserDefinedOperators:
def not_contain(self, a, b):
return a not in b
def some_other_function(self, a, b):
some other work here
Теперь я создаю перечисление, подобное этому
import operator
import enum
class MyOperators(enum.Enum):
LT = operator.gt
GT = operator.gt
NOT_CONTAIN = UserDefinedOperators().not_contain
У меня есть следующие различия в доступе к значению перечисления
>>> MyOperators
<enum 'MyOperators'>
>>> MyOperators.LT
<MyOperators.LT: <built-in function gt>>
>>> MyOperators.LT.value
<built-in function gt>
>>> MyOperators.LT.name
'LT'
>>> MyOperators.NOT_CONTAIN
<bound method UserDefinedOperators.not_contain of <__main__.UserDefinedOperators object at 0x100cdbeb0>>
>>> MyOperators.NOT_CONTAIN.value
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'value'
>>> MyOperators.NOT_CONTAIN.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'name'
>>>
Таким образом, в функции класса перечисление показывает
AttributeError: 'function' object has no attribute 'value'
Я прочитал в другом ответе SO, что он присваивается как функция, а не атрибуты перечисления, поэтому у него нет .value
.name
атрибутов или. Но тогда встроенный operator.lt
и operator.gt
также является функцией, тогда почему он работает нормально и имеет свойства .value и .name?
Ошибка действительно связана с нормальной функцией, а не только с функцией класса, но я хочу понять, в чем разница в модуле оператора? Как я могу добиться того же в своем классе?
Ответ №1:
Перечисление использует наличие __dunder__
метода __get__
для определения того, является ли объект функцией/классом. У всех функций и классов, созданных в Python, есть __get__
метод, но у встроенных функций его нет.
Чтобы обойти эту проблему, вы можете использовать модуль aenum
1 и его member
функцию:
from aenum import Enum, member
import operator
class UserDefinedOperators:
#
@staticmethod
def not_contain(self, a, b):
return a not in b
class MyOperators(Enum):
LT = operator.lt
GT = operator.gt
NOT_CONTAIN = member(UserDefinedOperators.not_contain)
и в использовании
>>> list(MyOperators)
[
<MyOperators.LT: <built-in function lt>>,
<MyOperators.GT: <built-in function gt>>,
<MyOperators.NOT_CONTAIN: <function UserDefinedOperators.not_contain at 0x7f9c875ed790>>,
]
Обратите внимание, что я заставил not_contain
быть staticmethod
А. Это уместно, поскольку not_contain
методу не требуются данные ни экземпляра, ни класса для выполнения своей работы. Это также означает, что вам не нужно создавать экземпляр UserDefinedOperators
с созданием элемента NOT_CONTAIN
перечисления.
1 Раскрытие информации: Я являюсь автором Python stdlib Enum
, enum34
бэкпорта и библиотеки расширенного перечисления ( aenum
).
Комментарии:
1. Я также отмечу, что класс, состоящий только из статических методов,-это просто наряженный словарь с функциями для значений.