Bhushan
Bhushan

Reputation: 2364

How to check if __str__ is implemented by an object

I want to dynamically implement __str__ method on a object if the object doesn't already implement it.

I try using hasattr(obj, '__str__') it always returns me true as it picks it up from object class.

Is there a way to determine if an object actually implements __str__ ?

I know I can use inspect.getmembers(obj) but I am searching for a more pythonic way

EDIT

class Employee(object):
def __init__(self, name, age, emp_code):
    self.name = name
    self.age  = age
    self.emp_code = emp_code

Test

e = Employee("A", 23, "E1")
print hasattr(e, '__str__')
>> True

I want a check that returns False instead of picking up the method inherited from object.

Upvotes: 12

Views: 4140

Answers (5)

Jonathan L
Jonathan L

Reputation: 10678

Use type(e).__dict__.get(method_name) to avoid KeyError if method_name not exists in class when using type(e).__dict__[method_name]

e = Employee("A", 23, "E1")
if type(e).__dict__.get('__str__'):
    print('__str__ implemented')
else:
    print('__str__ not implemented')

Upvotes: 0

Tronic
Tronic

Reputation: 1336

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.

Upvotes: 0

P.Panayotov
P.Panayotov

Reputation: 573

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.

Upvotes: 0

invert
invert

Reputation: 2086

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)

Upvotes: 1

Lennart Regebro
Lennart Regebro

Reputation: 172309

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.

Upvotes: 17

Related Questions