我想使用内部类的实例(在这种情况下为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
会引发:
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
。如果这是唯一的解决方案,我想了解为什么上述代码失败?
答案 0 :(得分:6)
在定义__init__
时,名称IdSignal
尚未绑定到该类。 (只有在评估class
语句的 entire 主体并将该评估的结果传递给相关的元类之后,这种情况才会发生。)但是,Cfg
是还不是class属性;它只是定义了__init__
的同一“作用域”中的名称,因此您无需限定名称。
def __init__(self, cfg=Cfg()):
self.cfg = cfg
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
语句部分中都没有定义名称。可以将它们视为创建类后将被丢弃的临时名称。