{"record":{"id":"db58dbf0ff1b52f0","repo":"PaddlePaddle/PaddleOCR","slug":"you-cannot-use-pop-on-a-self-class-name","errorCode":null,"errorMessage":"You cannot use ``pop`` on a {self.__class__.__name__} instance.","messagePattern":"You cannot use ``pop`` on a (.+?) instance\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"ppocr/modeling/heads/rec_unimernet_head.py","lineNumber":116,"sourceCode":"                self[class_fields[0].name] = first_field\n        else:\n            for field in class_fields:\n                v = getattr(self, field.name)\n                if v is not None:\n                    self[field.name] = v\n\n    def __delitem__(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``__delitem__`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def setdefault(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``setdefault`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def pop(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``pop`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def update(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``update`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def __getitem__(self, k):\n        if isinstance(k, str):\n            inner_dict = dict(self.items())\n            return inner_dict[k]\n        else:\n            return self.to_tuple()[k]\n\n    def __setattr__(self, name, value):\n        if name in self.keys() and value is not None:\n            super().__setitem__(name, value)","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/ppocr/modeling/heads/rec_unimernet_head.py#L98-L134","documentation":"pop is blocked on ModelOutput for the same reason as deletion/mutation: removing keys would desynchronize the dataclass fields from the mapping view, so the method unconditionally raises.","triggerScenarios":"Calling output.pop('key') or output.pop('key', default) on a ModelOutput instance, commonly in code that extracts-and-removes fields.","commonSituations":"Pipeline code that pops intermediate results as they are consumed; generic dict cleanup (popping None values); porting training-loop code that treats every output as a dict.","solutions":["Read the attribute and ignore it instead of removing: value = getattr(output, 'key', None)","Build a filtered copy: kept = ModelOutput(**{k: v for k, v in output.items() if k != 'key'})","Convert to dict for pop-style workflows: d = dict(output.items()); v = d.pop('key', None)"],"exampleFix":"# before\nloss = out.pop('loss', None)\n# after\nloss = getattr(out, 'loss', None)  # leave the object intact","handlingStrategy":"type-guard","validationCode":"def pop_like(mapping, key, default=None):\n    try:\n        return mapping[key], mapping  # non-destructive read\n    except KeyError:\n        return default, mapping","typeGuard":"def is_model_output(obj) -> bool:\n    return hasattr(obj, '__dataclass_fields__') and hasattr(obj, 'to_tuple')","tryCatchPattern":"try:\n    v = out.pop('loss')\nexcept Exception as e:\n    if 'pop' in str(e):\n        v = getattr(out, 'loss', None)\n    else:\n        raise","preventionTips":["Use getattr(out, key, default) for optional extraction","Switch to dict(out.items()) when a workflow truly needs pop","Never write extract-and-remove logic against head outputs"],"tags":["model-output","immutable","unimernet","api-misuse"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}