Python: Как использовать вложенное Enum в качестве аргумента по умолчанию для функции, в которую оно вложено? - PullRequest
1 голос
/ 27 мая 2020

Есть ли способ сделать что-то подобное в python?

from enum import Enum, auto
def some_func(mode = Mode.A):    
    class Mode(Enum):
        A = auto()
    print(mode == Mode.A)

желаемый результат

>>> some_func()
True

Приведенный выше фрагмент не работает с NameError: name 'Mode' is not defined предположительно потому, что class Mode не определяется, когда интерпретатор читает def some_func(mode = Mode.A):

Вы, конечно, можете поместить Enum вне функции, но, если то, что я предлагаю, или что-то подобное сработало, я бы предпочел оставить его внутри. Хранение его внутри инкапсулирует режим, в котором он предназначен для использования, надеюсь, позволяет синтаксису . отличать guish от других похожих классов Mode.

Я знаю, что многие * Код 1024 * просто использует для этой цели строки, не беспокоясь о Enums. Однако я хотел бы найти решение, используя Enums. Перечисления легче поддерживать, и они помогают IDE генерировать автозавершение кода и т. Д. c.

Есть ли хороший способ сделать эту работу?

Ответы [ 2 ]

2 голосов
/ 27 мая 2020

Вызывающий функцию не имеет доступа к локальным переменным, объявленным внутри функции. Следовательно, локально объявленные классы не могут быть частью внешнего интерфейса.

Если перечисление вообще не предназначено для доступа вызывающей стороне, то его не следует принимать в качестве параметра; просто объявите и создайте экземпляр перечисления внутри тела функции и держите его полностью скрытым от вызывающего.

Если перечисление должно быть доступно вызывающему как часть интерфейса publi c, ему необходимо должны быть объявлены в той же / более высокой области, что и сама функция (т.е. вне функции).

Если вы хотите инкапсулировать функцию и перечисление, класс будет типичным способом сделать это (т. е. функция и перечисление будут членами класса publi c).


Если вы действительно хотите иметь доступ к классу enum как члену функции вы могли бы сделать что-нибудь эксцентричное c вроде:

from enum import Enum, auto
from typing import Optional


class SomeFunc:

    class Mode(Enum):
        A = auto()
        B = auto()

    def __call__(self, mode: Optional['Mode'] = None) -> None:
        if mode is None:
            mode = self.Mode.A
        print(mode == self.Mode.A)


some_func = SomeFunc()

some_func()
some_func(some_func.Mode.B)
0 голосов
/ 27 мая 2020

Он работает, если вы сначала определяете содержимое перечисления, которое может быть вместе внутри родительского класса. Вы также можете выполнить приведение типа к перечислению и выдать ошибку приведения, если предоставленная строка не может быть приведена к перечислению. Это был бы точный способ проверить ввод строки. Я не записал это, потому что не знаю, поможет ли это вам. Удачи!

# Here the code a bit modified
from enum import Enum, auto  
class Parent():  
    class Mode(Enum):  
        A = auto()  
    @staticmethod  
    def some_func(mode):  
        print(mode)        
Parent.some_func(Parent.Mode.A)     
...