Reputation: 2364
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
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
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
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
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
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