Экземпляр внутреннего класса в качестве значения по умолчанию для метода внешнего класса - PullRequest
0 голосов
/ 19 декабря 2018

Я хотел бы использовать экземпляр внутреннего класса (в данном случае namedtuple, хотя точно такие же симптомы возникают для внутреннего класса, определенного с class) в качестве значения по умолчанию для метода внешнего класса (вэтот случай конструктор).Однако, когда этот код импортируется из другого модуля, определение внешнего класса, по-видимому, отсутствует.

Пример:

# mymodule.py

from typing import NamedTuple, Tuple

class IdSignal():
    Cfg = NamedTuple('IdSignalCfg', [
        ('nfft', int),
        ('limits', Tuple[float, float]),
        ('min_spacing', float),
        ('nmix', int)])
    Cfg.__new__.__defaults__ = (
        512,
        (1500, 7500),
        200,
        3
    )

    def __init__(self, cfg = IdSignal.Cfg()):
        self.cfg = cfg

Теперь выполняется import mymodule throws:

Exception has occurred: NameError
name 'IdSignal' is not defined
  File "...", line 18, in IdSignal
    def __init__(self, cfg = IdSignal.Cfg()):
  File "...", line 5, in <module>
    class IdSignal():
  ...
    import mymodule

Смущает, что и pylint, и mypy не распознают никаких ошибок в приведенном выше коде.

Можно ли это сделать любым другим способом?

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

1 Ответ

0 голосов
/ 19 декабря 2018

В момент определения __init__ имя IdSignal еще не привязано к классу.(Этого не произойдет, пока не будет проанализировано полное тело оператора class и результат этой оценки передается в соответствующий метакласс.) Однако Cfg также еще не является классоматрибутов;это просто имя в той же «области видимости», в которой определено __init__, поэтому вам не нужно указывать имя.

def __init__(self, cfg=Cfg()):
    self.cfg = cfg

A class, например

class Foo:
    x = 3
    def __init__(self, y):
        self.y = y

примерно эквивалентно

# These names don't really matter, but I'm using different
# names than what the attributes will be just to emphasize
# the point that they really are distinct objects before
# the new class is ever created.

class_x = 3

def some_init(self, y):
    self.y = y

Foo = type('Foo', (object,), {'__init__': some_init, 'x': class_x})

Обратите внимание, что имя Foo не существует до самого конца.Оператор class не определяет новую область видимости, как модуль или функция, но и имена не определены в части оператора class любой включающей области;думайте о них как о временных именах, которые отбрасываются после создания класса.

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