Skip to main content
 首页 » 编程设计

python之内部类的实例作为外部类方法的默认值

2025年05月04日13langtianya

我想使用一个内部类的实例(在本例中是一个 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 在 构造函数中。如果这是唯一的解决方案,我想了解为什么上面的代码失败了?

请您参考如下方法:

在定义 __init__ 时,名称 IdSignal 尚未绑定(bind)到该类。 (直到评估 class 语句的整个主体,并且评估的结果被传递给相关的元类,才会发生这种情况。)但是, cfg 也还不是类属性;它只是在定义 __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 语句中定义的名称也不是任何封闭作用域的一部分;将它们视为创建类后丢弃的临时名称。