Avoid Calling Magic Methods

ID

python.avoid_calling_magic_methods

Severity

low

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

Python

Tags

best-practice, code-style

Description

Reports direct calls to dunder methods (obj.str(), obj.len(), obj.add(other), …​). Dunder methods are the protocol the interpreter dispatches to; user code should call the corresponding builtin or operator (str(obj), len(obj), obj + other). Calling the dunder directly bypasses the resolution rules (descriptor protocol, fallbacks, type coercion) and produces subtle wrong-behaviour bugs.

obj.__str__()                 # FLAW — use str(obj)
obj.__len__()                 # FLAW — use len(obj)
obj.__eq__(other)             # FLAW — use obj == other

super().__init__()            # OK
str(obj)                      # OK
len(obj)                      # OK

Rationale

The classic case is obj.eq(other) returning NotImplemented (Python’s protocol for "I don’t know how to compare these — defer to the right operand"). The == operator handles NotImplemented correctly; calling eq directly does not, so the result is NotImplemented instead of True/False. The same shape applies to every comparison and arithmetic dunder.

Calls to super().init(…​) are exempt — that is the canonical way to invoke the parent constructor.

Remediation

Use the public Python equivalent:

Dunder Use instead

str

str(obj)

repr

repr(obj)

len

len(obj)

iter

iter(obj) / for x in obj

bool

bool(obj) / if obj

add, sub, …​

the operator (+, -, …​)

eq, lt, …​

the comparison operator (==, <, …​)