Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

245
Vistas
__str__ wrapper in custom Exception

Why does the below code print error msg instead of ABC\nerror msg?

class CustomException(Exception):
    """ABC"""
    def __init__(self, *args):
        super().__init__(*args)
        self.__str__ = self._wrapper(self.__str__)
    def _wrapper(self, f):
        def _inner(*args, **kwargs):
            return self.__doc__ + '\n' + f(*args, **kwargs)
        return _inner

print(CustomException('error msg'))
over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Forget the Exception class for now. Consider this:

class A:
    def __str__(self):
        return 'A'

obj = A()
print(obj)
obj.__str__ = lambda x: 'B'
print(obj)
A.__str__ = lambda x: 'B'
print(obj)

output:

A
A   # Not B !
B

Dunder methods' lookup is different in Python. From docs:

For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.

What you want to achieve is:

class CustomException(Exception):
    """ABC"""

    def __init__(self, *args):
        super().__init__(*args)

    def __str__(self):
        return self.__doc__ + '\n' + super().__str__()


print(CustomException('error msg'))

output:

ABC
error msg
over 4 years ago · Santiago Trujillo Denunciar

0

Operations backed by special methods usually explicitly look up the special method as a proper method not just as a callable attribute. Concretely, instead of self.__str__ the interpreter roughly looks at type(self).__str__.__get__(self, type(self)) – i.e. a descriptor __str__ on the class to be bound with the instance. To override a special method, it is thus necessary to override the class' descriptor instead of the instance' attribute.

This can be done by a) declaring the special method as a slot, which handles the type(self).__str__ part, and b) assigning a function, which handles the __get__(self, type(self)) part.

class CustomException(Exception):
    """ABC"""
    __slots__ = ("__str__",)  # <<< magic

    def __init__(self, *args):
        super().__init__(*args)
        # vvv self.__str__ is the class' slot
        self.__str__ = self._wrapper(super().__str__)
        #                            AAA real __str__ lives on the super class
    def _wrapper(self, f):
        def _inner(*args, **kwargs):
            return self.__doc__ + '\n' + f(*args, **kwargs)
        return _inner

print(CustomException('error msg'))

Note that since every instance behaves the same in this case, it is advisable to just define a new __str__ method in practice.

over 4 years ago · Santiago Trujillo Denunciar

0

As per @khelwood's reply in the comments this code works as intended:

class CustomException(Exception):
    """ABC"""
    def __init__(self, *args):
        super().__init__(*args)
        self.__class__.__str__ = self._wrapper(self.__str__)
    def _wrapper(self, f):
        def _inner(*args, **kwargs):
            return self.__doc__ + '\n' + f()
        return _inner

but I ended up with this equivalent (@MisterMiyagi):

class CustomException(Exception):
    """ABC"""
    def __str__(self):
        return self.__doc__ + '\n' + super().__str__()
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda