The Python Oracle

How to check if __str__ is implemented by an object

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Dreaming in Puzzles

--

Chapters
00:00 How To Check If __str__ Is Implemented By An Object
00:44 Accepted Answer Score 17
01:18 Answer 2 Score 1
01:39 Answer 3 Score 0
02:07 Answer 4 Score 0
02:43 Thank you

--

Full question
https://stackoverflow.com/questions/1962...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python

#avk47



ACCEPTED ANSWER

Score 17


Since what you want to check is if it has a __str__ implementation that is not the default object.__str__. Therefore, you can do this:

Foo.__str__ is not object.__str__

To check with instantiated objects you need to check on the class:

type(f).__str__ is not object.__str__

This will also work even if Foo doesn't implement __str__ directly, but inherited it from another class than object, which seems to be what you want.




ANSWER 2

Score 1


Any object inheriting from the object base will have a __str__ method, so testing if it exists is negligible.

You could store a flag attribute on the object, and test for that instead:

if not getattr(obj, 'has_str_override_flag'):
    override_str_here(obj)
    setattr(obj, 'has_str_override_flag', True)



ANSWER 3

Score 0


Well in you object there is __dict__ that contains all the methods and variables that the object has. You can check if a given object has __str__() method implemented by

'__str__' in Employee.__dict__

or

'__str__' in vars(Employee)

There is no difference between vars() and __dict__, just vars() is more Pythonic.




ANSWER 4

Score 0


It turns out that built-in types rely on object.__str__ to do their (smart) formatting. I really only wanted to eliminate useless strings like <__main__.Foo object at 0x10299d390> and still have dict and other types printed properly. My solution:

objre = re.compile(r"<.* object at 0x[0-9a-f]+>")
if objre.fullmatch(str(obj)):
    # Do smarter formatting

This won't catch default formatting of modules, functions etc, for which source code could be shown instead via inspect.getsource(), but I am not displaying them in my variable inspector anyway.