d2l-ai/d2l-zh · error · NotImplementedError

NotImplementedError

Error message

NotImplementedError

What it means

A NotImplementedError raised by d2l.paddle.Encoder.forward. Encoder is the abstract encoder interface of the encoder-decoder architecture in the PaddlePaddle edition; forward is intentionally unimplemented. A subclass that fails to override forward (or a direct instantiation) raises as soon as the layer is invoked.

Source

Thrown at d2l/paddle.py:949

    text = preprocess_nmt(read_data_nmt())
    source, target = tokenize_nmt(text, num_examples)
    src_vocab = d2l.Vocab(source, min_freq=2,
                          reserved_tokens=['<pad>', '<bos>', '<eos>'])
    tgt_vocab = d2l.Vocab(target, min_freq=2,
                          reserved_tokens=['<pad>', '<bos>', '<eos>'])
    src_array, src_valid_len = build_array_nmt(source, src_vocab, num_steps)
    tgt_array, tgt_valid_len = build_array_nmt(target, tgt_vocab, num_steps)
    data_arrays = (src_array, src_valid_len, tgt_array, tgt_valid_len)
    data_iter = d2l.load_array(data_arrays, batch_size)
    return data_iter, src_vocab, tgt_vocab

class Encoder(nn.Layer):
    """编码器-解码器架构的基本编码器接口"""
    def __init__(self, **kwargs):
        super(Encoder, self).__init__(**kwargs)

    def forward(self, X, *args):
        raise NotImplementedError

class Decoder(nn.Layer):
    """编码器-解码器架构的基本解码器接口

    Defined in :numref:`sec_encoder-decoder`"""
    def __init__(self, **kwargs):
        super(Decoder, self).__init__(**kwargs)

    def init_state(self, enc_outputs, *args):
        raise NotImplementedError

    def forward(self, X, state):
        raise NotImplementedError

class EncoderDecoder(nn.Layer):
    """编码器-解码器架构的基类

    Defined in :numref:`sec_encoder-decoder`"""

View on GitHub (pinned to e6b18ccea7)

Solutions

  1. Subclass and implement forward: class MyEncoder(d2l.Encoder): def forward(self, X, *args): ...
  2. Rename 'call' to 'forward' when porting from the TensorFlow edition.
  3. Use the provided d2l.Seq2SeqEncoder instead of the abstract base for standard seq2seq.
  4. Verify the signature matches (self, X, *args) so EncoderDecoder.forward can invoke it.

Example fix

# before
enc = d2l.Encoder()
enc(X)  # NotImplementedError
# after
class MyEncoder(d2l.Encoder):
    def forward(self, X, *args):
        return paddle.identity(X)
enc = MyEncoder()
enc(X)
Defensive patterns

Strategy: type-guard

Type guard

def is_concrete_encoder(enc) -> bool:
    return (isinstance(enc, d2l.Encoder)
            and type(enc).forward is not d2l.Encoder.forward)

Try / catch

try:
    enc(X)
except NotImplementedError:
    raise TypeError(f'{type(enc).__name__} must override Encoder.forward(X, *args)') from None

Prevention

When it happens

Trigger: Calling d2l.Encoder()(X) directly; defining an encoder subclass with 'call' instead of 'forward' (TensorFlow spelling) so Paddle never dispatches to it; forgetting the override while implementing a custom architecture.

Common situations: Porting the TensorFlow d2l edition to Paddle and keeping the 'call' method name; exercises in sec_encoder-decoder where users build their own encoder; partial IDE-generated subclasses.

Related errors


AI-assisted analysis of d2l-ai/d2l-zh@e6b18ccea7 (2026-08-14). Data as JSON: /api/errors/d6bf67a18256cfee. Report an issue: GitHub.